Răsfoiți Sursa

feat: add service for notifications

KernelDeimos 11 luni în urmă
părinte
comite
a1e6887bf9

+ 3 - 0
packages/backend/src/CoreModule.js

@@ -242,6 +242,9 @@ const install = async ({ services, app, useapi }) => {
     
     const { BroadcastService } = require('./services/BroadcastService');
     services.registerService('broadcast', BroadcastService);
+    
+    const { NotificationService } = require('./services/NotificationService');
+    services.registerService('notification', NotificationService);
 }
 
 const install_legacy = async ({ services }) => {

+ 65 - 0
packages/backend/src/services/NotificationService.js

@@ -0,0 +1,65 @@
+const BaseService = require("./BaseService");
+const { DB_WRITE } = require("./database/consts");
+
+const UsernameNotifSelector = username => async (self) => {
+    const svc_getUser = self.services.get('get-user');
+    const user = await svc_getUser.get_user({ username });
+    return [user.id];
+};
+
+class NotificationService extends BaseService {
+    static MODULES = {
+        uuidv4: require('uuid').v4,
+    }
+
+    async _init () {
+        const svc_database = this.services.get('database');
+        this.db = svc_database.get(DB_WRITE, 'notification');
+        
+        const svc_script = this.services.get('script');
+        svc_script.register('test-notification', async ({ log }, [username, summary]) => {
+            log('creating notification: ' + summary);
+            
+            this.notify(UsernameNotifSelector(username), { summary });
+        });
+    }
+    async notify (selector, notification) {
+        const uid = this.modules.uuidv4();
+        const svc_event = this.services.get('event');
+        const user_id_list = await selector(this);
+        svc_event.emit('outer.gui.notif.message', {
+            user_id_list,
+            response: {
+                uid,
+                notification,
+            },
+        });
+        
+        const ll = o => {
+            this.log.noticeme('debug: ' + require('node:util').inspect(o));
+            return o;
+        };
+        
+        (async () => {
+            for ( const user_id of user_id_list ) {
+                await this.db.write(...ll([
+                    'INSERT INTO `notification` ' +
+                    '(`user_id`, `uid`, `value`) ' +
+                    'VALUES (?, ?, ?)',
+                    [user_id, uid, JSON.stringify(notification)],
+                ]));
+            }
+            svc_event.emit('outer.gui.notif.persisted', {
+                user_id_list,
+                response: {
+                    uid,
+                },
+            });
+        })();
+    }
+}
+
+module.exports = {
+    NotificationService,
+    UsernameNotifSelector,
+};

+ 0 - 21
packages/backend/src/services/WSPushService.js

@@ -68,11 +68,6 @@ class WSPushService  extends AdvancedBase {
 
         Object.assign(response, metadata);
 
-        const io = socketio.getio();
-        for ( const user_id of user_id_list ) {
-            io.to(user_id).emit('item.added', response);
-        }
-
         this.svc_event.emit('outer.gui.item.added', {
             user_id_list,
             response,
@@ -107,11 +102,6 @@ class WSPushService  extends AdvancedBase {
 
         Object.assign(response, metadata);
 
-        const io = socketio.getio();
-        for ( const user_id of user_id_list ) {
-            io.to(user_id).emit('item.updated', response);
-        }
-        
         this.svc_event.emit('outer.gui.item.updated', {
             user_id_list,
             response,
@@ -147,11 +137,6 @@ class WSPushService  extends AdvancedBase {
         response.old_path = old_path;
         Object.assign(response, metadata);
 
-        const io = socketio.getio();
-        for ( const user_id of user_id_list ) {
-            io.to(user_id).emit('item.moved', response);
-        }
-
         this.svc_event.emit('outer.gui.item.moved', {
             user_id_list,
             response,
@@ -185,10 +170,6 @@ class WSPushService  extends AdvancedBase {
 
         Object.assign(response, metadata);
 
-        const io = socketio.getio();
-        for ( const user_id of user_id_list ) {
-            io.to(user_id).emit('item.pending', response);
-        }
         this.svc_event.emit('outer.gui.item.pending', {
             user_id_list,
             response,
@@ -248,8 +229,6 @@ class WSPushService  extends AdvancedBase {
     }
     
     async _on_outer_gui (key, { user_id_list, response }, meta) {
-        if ( ! meta.from_outside ) return;
-
         key = key.slice('outer.gui.'.length);
 
         const { socketio } = this.modules;

+ 5 - 1
packages/backend/src/services/database/SqliteDatabaseAccessService.js

@@ -42,7 +42,7 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
         this.db = new Database(this.config.path);
 
         // Database upgrade logic
-        const TARGET_VERSION = 8;
+        const TARGET_VERSION = 9;
 
         if ( do_setup ) {
             this.log.noticeme(`SETUP: creating database at ${this.config.path}`);
@@ -105,6 +105,10 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
             upgrade_files.push('0010_add-git-app.sql');
         }
 
+        if ( user_version <= 8 ) {
+            upgrade_files.push('0011_notification.sql');
+        }
+
         if ( upgrade_files.length > 0 ) {
             this.log.noticeme(`Database out of date: ${this.config.path}`);
             this.log.noticeme(`UPGRADING DATABASE: ${user_version} -> ${TARGET_VERSION}`);

+ 8 - 0
packages/backend/src/services/database/sqlite_setup/0011_notification.sql

@@ -0,0 +1,8 @@
+CREATE TABLE `notification` (
+    `id` INTEGER PRIMARY KEY AUTOINCREMENT,
+    `user_id` INTEGER NOT NULL,
+    `uid` TEXT NOT NULL UNIQUE,
+    `value` JSON NOT NULL,
+    `read` tinyint(1) DEFAULT '0',
+    `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);

+ 6 - 0
src/UI/UIDesktop.js

@@ -110,6 +110,12 @@ async function UIDesktop(options){
         if(msg.is_empty)
             $(`.window[data-path="${html_encode(window.trash_path)}" i]`).find('.item-container').empty();
     })
+    
+    window.socket.on('notif.message', ({ notification }) => {
+        UINotification({
+            content: notification.summary
+        });
+    });
 
     window.socket.on('app.opened', async (app) => {
         // don't update if this is the original client that initiated the action