aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Iaroslav <yavoloh@mail.ru>2021-10-23 19:16:01 +0500
committerLibravatar GitHub <noreply@github.com>2021-10-23 19:46:01 +0530
commit4d02744dfab8a49075b82a5ddbdc02e08c7e8a66 (patch)
treedc7b08818a8f116d41886924552c92719c4d081a /src
parentchore: upgrade npm modules (diff)
downloadferdium-app-4d02744dfab8a49075b82a5ddbdc02e08c7e8a66.tar.gz
ferdium-app-4d02744dfab8a49075b82a5ddbdc02e08c7e8a66.tar.zst
ferdium-app-4d02744dfab8a49075b82a5ddbdc02e08c7e8a66.zip
Add active dialog title feature (#2114)
https://github.com/getferdi/ferdi/issues/1280 WhatsApp-like services can set active dialog title to the app title eg. Ferdi - WhatsApp - Contact Name
Diffstat (limited to 'src')
-rw-r--r--src/actions/service.ts4
-rw-r--r--src/models/Service.js2
-rw-r--r--src/stores/ServicesStore.js21
-rw-r--r--src/webview/dialogTitle.ts33
-rw-r--r--src/webview/lib/RecipeWebview.js24
-rw-r--r--src/webview/lib/Userscript.js10
-rw-r--r--src/webview/recipe.js5
7 files changed, 96 insertions, 3 deletions
diff --git a/src/actions/service.ts b/src/actions/service.ts
index e56513f8f..aa02c860a 100644
--- a/src/actions/service.ts
+++ b/src/actions/service.ts
@@ -39,6 +39,10 @@ export default {
39 serviceId: PropTypes.string.isRequired, 39 serviceId: PropTypes.string.isRequired,
40 count: PropTypes.object.isRequired, 40 count: PropTypes.object.isRequired,
41 }, 41 },
42 setDialogTitle: {
43 serviceId: PropTypes.string.isRequired,
44 dialogTitle: PropTypes.string.isRequired,
45 },
42 setWebviewReference: { 46 setWebviewReference: {
43 serviceId: PropTypes.string.isRequired, 47 serviceId: PropTypes.string.isRequired,
44 webview: PropTypes.object.isRequired, 48 webview: PropTypes.object.isRequired,
diff --git a/src/models/Service.js b/src/models/Service.js
index d94f55692..3cf0523c3 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -37,6 +37,8 @@ export default class Service {
37 37
38 @observable unreadIndirectMessageCount = 0; 38 @observable unreadIndirectMessageCount = 0;
39 39
40 @observable dialogTitle = '';
41
40 @observable order = DEFAULT_SERVICE_ORDER; 42 @observable order = DEFAULT_SERVICE_ORDER;
41 43
42 @observable isEnabled = true; 44 @observable isEnabled = true;
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 4f7ad7442..e52d661f3 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -82,6 +82,7 @@ export default class ServicesStore extends Store {
82 this.actions.service.setUnreadMessageCount.listen( 82 this.actions.service.setUnreadMessageCount.listen(
83 this._setUnreadMessageCount.bind(this), 83 this._setUnreadMessageCount.bind(this),
84 ); 84 );
85 this.actions.service.setDialogTitle.listen(this._setDialogTitle.bind(this));
85 this.actions.service.openWindow.listen(this._openWindow.bind(this)); 86 this.actions.service.openWindow.listen(this._openWindow.bind(this));
86 this.actions.service.filter.listen(this._filter.bind(this)); 87 this.actions.service.filter.listen(this._filter.bind(this));
87 this.actions.service.resetFilter.listen(this._resetFilter.bind(this)); 88 this.actions.service.resetFilter.listen(this._resetFilter.bind(this));
@@ -646,6 +647,12 @@ export default class ServicesStore extends Store {
646 service.unreadIndirectMessageCount = count.indirect; 647 service.unreadIndirectMessageCount = count.indirect;
647 } 648 }
648 649
650 @action _setDialogTitle({ serviceId, dialogTitle }) {
651 const service = this.one(serviceId);
652
653 service.dialogTitle = dialogTitle;
654 }
655
649 @action _setWebviewReference({ serviceId, webview }) { 656 @action _setWebviewReference({ serviceId, webview }) {
650 const service = this.one(serviceId); 657 const service = this.one(serviceId);
651 658
@@ -741,6 +748,16 @@ export default class ServicesStore extends Store {
741 748
742 break; 749 break;
743 } 750 }
751 case 'active-dialog-title': {
752 debug(`Received active dialog title from '${serviceId}'`, args[0]);
753
754 this.actions.service.setDialogTitle({
755 serviceId,
756 dialogTitle: args[0],
757 });
758
759 break;
760 }
744 case 'notification': { 761 case 'notification': {
745 const { options } = args[0]; 762 const { options } = args[0];
746 763
@@ -1063,7 +1080,9 @@ export default class ServicesStore extends Store {
1063 const service = this.active; 1080 const service = this.active;
1064 if (service) { 1081 if (service) {
1065 this.actions.service.focusService({ serviceId: service.id }); 1082 this.actions.service.focusService({ serviceId: service.id });
1066 document.title = `Ferdi - ${service.name}`; 1083 document.title = `Ferdi - ${service.name} ${
1084 service.dialogTitle ? ` - ${service.dialogTitle}` : ''
1085 }`;
1067 } else { 1086 } else {
1068 debug('No service is active'); 1087 debug('No service is active');
1069 } 1088 }
diff --git a/src/webview/dialogTitle.ts b/src/webview/dialogTitle.ts
new file mode 100644
index 000000000..f9a1aac6f
--- /dev/null
+++ b/src/webview/dialogTitle.ts
@@ -0,0 +1,33 @@
1import { ipcRenderer } from 'electron';
2
3const debug = require('debug')('Ferdi:Plugin:DialogTitleHandler');
4
5export class DialogTitleHandler {
6 titleCache: { title: string };
7
8 constructor() {
9 this.titleCache = {
10 title: '',
11 };
12 }
13
14 safeGetTitle(title: string | undefined | null) {
15 if (!title) {
16 return '';
17 }
18
19 return title;
20 }
21
22 setDialogTitle(title: string | undefined | null) {
23 const newTitle = this.safeGetTitle(title);
24 if (this.titleCache.title === newTitle) {
25 return;
26 }
27
28 debug('Sending active dialog title to host %s', newTitle);
29 ipcRenderer.sendToHost('active-dialog-title', newTitle);
30
31 this.titleCache.title = newTitle;
32 }
33}
diff --git a/src/webview/lib/RecipeWebview.js b/src/webview/lib/RecipeWebview.js
index f1d493e7c..ebe88ed85 100644
--- a/src/webview/lib/RecipeWebview.js
+++ b/src/webview/lib/RecipeWebview.js
@@ -5,8 +5,14 @@ import { pathExistsSync, readFileSync, existsSync } from 'fs-extra';
5const debug = require('debug')('Ferdi:Plugin:RecipeWebview'); 5const debug = require('debug')('Ferdi:Plugin:RecipeWebview');
6 6
7class RecipeWebview { 7class RecipeWebview {
8 constructor(badgeHandler, notificationsHandler, sessionHandler) { 8 constructor(
9 badgeHandler,
10 dialogTitleHandler,
11 notificationsHandler,
12 sessionHandler,
13 ) {
9 this.badgeHandler = badgeHandler; 14 this.badgeHandler = badgeHandler;
15 this.dialogTitleHandler = dialogTitleHandler;
10 this.notificationsHandler = notificationsHandler; 16 this.notificationsHandler = notificationsHandler;
11 this.sessionHandler = sessionHandler; 17 this.sessionHandler = sessionHandler;
12 18
@@ -59,6 +65,17 @@ class RecipeWebview {
59 } 65 }
60 66
61 /** 67 /**
68 * Set the active dialog title to the app title
69 *
70 * @param {string | undefined | null} title Set the active dialog title
71 * to the app title
72 * eg. WhatsApp contact name
73 */
74 setDialogTitle(title) {
75 this.dialogTitleHandler.setDialogTitle(title);
76 }
77
78 /**
62 * Safely parse the given text into an integer 79 * Safely parse the given text into an integer
63 * 80 *
64 * @param {string | number | undefined | null} text to be parsed 81 * @param {string | number | undefined | null} text to be parsed
@@ -127,7 +144,10 @@ class RecipeWebview {
127 } 144 }
128 145
129 clearStorageData(serviceId, targetsToClear) { 146 clearStorageData(serviceId, targetsToClear) {
130 ipcRenderer.send('clear-storage-data', { serviceId, targetsToClear }); 147 ipcRenderer.send('clear-storage-data', {
148 serviceId,
149 targetsToClear,
150 });
131 } 151 }
132 152
133 releaseServiceWorkers() { 153 releaseServiceWorkers() {
diff --git a/src/webview/lib/Userscript.js b/src/webview/lib/Userscript.js
index bed2b1ff8..f7bb99206 100644
--- a/src/webview/lib/Userscript.js
+++ b/src/webview/lib/Userscript.js
@@ -60,6 +60,16 @@ export default class Userscript {
60 } 60 }
61 61
62 /** 62 /**
63 * Set active dialog title to the app title
64 * @param {*} title Dialog title
65 */
66 setDialogTitle(title) {
67 if (this.recipe && this.recipe.setDialogTitle) {
68 this.recipe.setDialogTitle(title);
69 }
70 }
71
72 /**
63 * Inject CSS files into the current page 73 * Inject CSS files into the current page
64 * 74 *
65 * @param {...string} files 75 * @param {...string} files
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index 5cab28c09..92c1ee2f0 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -23,6 +23,7 @@ import RecipeWebview from './lib/RecipeWebview';
23import Userscript from './lib/Userscript'; 23import Userscript from './lib/Userscript';
24 24
25import { BadgeHandler } from './badge'; 25import { BadgeHandler } from './badge';
26import { DialogTitleHandler } from './dialogTitle';
26import { SessionHandler } from './sessionHandler'; 27import { SessionHandler } from './sessionHandler';
27import contextMenu from './contextMenu'; 28import contextMenu from './contextMenu';
28import { 29import {
@@ -51,6 +52,8 @@ const debug = require('debug')('Ferdi:Plugin');
51 52
52const badgeHandler = new BadgeHandler(); 53const badgeHandler = new BadgeHandler();
53 54
55const dialogTitleHandler = new DialogTitleHandler();
56
54const sessionHandler = new SessionHandler(); 57const sessionHandler = new SessionHandler();
55 58
56const notificationsHandler = new NotificationsHandler(); 59const notificationsHandler = new NotificationsHandler();
@@ -106,6 +109,7 @@ contextBridge.exposeInMainWorld('ferdi', {
106 open: window.open, 109 open: window.open,
107 setBadge: (direct, indirect) => badgeHandler.setBadge(direct, indirect), 110 setBadge: (direct, indirect) => badgeHandler.setBadge(direct, indirect),
108 safeParseInt: text => badgeHandler.safeParseInt(text), 111 safeParseInt: text => badgeHandler.safeParseInt(text),
112 setDialogTitle: title => dialogTitleHandler.setDialogTitle(title),
109 displayNotification: (title, options) => 113 displayNotification: (title, options) =>
110 notificationsHandler.displayNotification(title, options), 114 notificationsHandler.displayNotification(title, options),
111 getDisplayMediaSelector, 115 getDisplayMediaSelector,
@@ -200,6 +204,7 @@ class RecipeController {
200 try { 204 try {
201 this.recipe = new RecipeWebview( 205 this.recipe = new RecipeWebview(
202 badgeHandler, 206 badgeHandler,
207 dialogTitleHandler,
203 notificationsHandler, 208 notificationsHandler,
204 sessionHandler, 209 sessionHandler,
205 ); 210 );