mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-26 19:34:04 +01:00
Introduce infrastructure for Notification Profiles
This commit is contained in:
231
ts/sql/Server.ts
231
ts/sql/Server.ts
@@ -211,8 +211,9 @@ import {
|
||||
getGroupSendMemberEndorsement,
|
||||
replaceAllEndorsementsForGroup,
|
||||
} from './server/groupSendEndorsements';
|
||||
import type { GifType } from '../components/fun/panels/FunPanelGifs';
|
||||
import { INITIAL_EXPIRE_TIMER_VERSION } from '../util/expirationTimer';
|
||||
import type { GifType } from '../components/fun/panels/FunPanelGifs';
|
||||
import type { NotificationProfileType } from '../types/NotificationProfile';
|
||||
|
||||
type ConversationRow = Readonly<{
|
||||
json: string;
|
||||
@@ -363,6 +364,9 @@ export const DataReader: ServerReadableInterface = {
|
||||
getCallHistoryGroups,
|
||||
hasGroupCallHistoryMessage,
|
||||
|
||||
getAllNotificationProfiles,
|
||||
getNotificationProfileById,
|
||||
|
||||
callLinkExists,
|
||||
defunctCallLinkExists,
|
||||
getAllCallLinks,
|
||||
@@ -586,6 +590,12 @@ export const DataWriter: ServerWritableInterface = {
|
||||
_deleteAllStoryReads,
|
||||
addNewStoryRead,
|
||||
|
||||
_deleteAllNotificationProfiles,
|
||||
createNotificationProfile,
|
||||
deleteNotificationProfileById,
|
||||
markNotificationProfileDeleted,
|
||||
updateNotificationProfile,
|
||||
|
||||
removeAll,
|
||||
removeAllConfiguration,
|
||||
eraseStorageServiceState,
|
||||
@@ -6859,6 +6869,224 @@ function countStoryReadsByConversation(
|
||||
);
|
||||
}
|
||||
|
||||
type NotificationProfileForDatabase = Readonly<
|
||||
{
|
||||
emoji: string | null;
|
||||
allowAllCalls: 0 | 1;
|
||||
allowAllMentions: 0 | 1;
|
||||
scheduleEnabled: 0 | 1;
|
||||
allowedMembersJson: string | null;
|
||||
scheduleStartTime: number | null;
|
||||
scheduleEndTime: number | null;
|
||||
scheduleDaysEnabledJson: string | null;
|
||||
deletedAtTimestampMs: number | null;
|
||||
storageID: string | null;
|
||||
storageVersion: number | null;
|
||||
storageNeedsSync: 0 | 1;
|
||||
} & Omit<
|
||||
NotificationProfileType,
|
||||
| 'emoji'
|
||||
| 'allowAllCalls'
|
||||
| 'allowAllMentions'
|
||||
| 'scheduleEnabled'
|
||||
| 'allowedMembers'
|
||||
| 'scheduleStartTime'
|
||||
| 'scheduleEndTime'
|
||||
| 'scheduleDaysEnabled'
|
||||
| 'deletedAtTimestampMs'
|
||||
| 'storageID'
|
||||
| 'storageVersion'
|
||||
| 'storageNeedsSync'
|
||||
>
|
||||
>;
|
||||
|
||||
function hydrateNotificationProfile(
|
||||
profile: NotificationProfileForDatabase
|
||||
): NotificationProfileType {
|
||||
return {
|
||||
...omit(profile, ['allowedMembersJson', 'scheduleDaysEnabledJson']),
|
||||
emoji: profile.emoji || undefined,
|
||||
allowAllCalls: Boolean(profile.allowAllCalls),
|
||||
allowAllMentions: Boolean(profile.allowAllMentions),
|
||||
scheduleEnabled: Boolean(profile.scheduleEnabled),
|
||||
allowedMembers: profile.allowedMembersJson
|
||||
? new Set(JSON.parse(profile.allowedMembersJson))
|
||||
: new Set(),
|
||||
scheduleStartTime: profile.scheduleStartTime || undefined,
|
||||
scheduleEndTime: profile.scheduleEndTime || undefined,
|
||||
scheduleDaysEnabled: profile.scheduleDaysEnabledJson
|
||||
? JSON.parse(profile.scheduleDaysEnabledJson)
|
||||
: undefined,
|
||||
deletedAtTimestampMs: profile.deletedAtTimestampMs || undefined,
|
||||
storageID: profile.storageID || undefined,
|
||||
storageVersion: profile.storageVersion || undefined,
|
||||
storageNeedsSync: Boolean(profile.storageNeedsSync),
|
||||
storageUnknownFields: profile.storageUnknownFields || undefined,
|
||||
};
|
||||
}
|
||||
function freezeNotificationProfile(
|
||||
profile: NotificationProfileType
|
||||
): NotificationProfileForDatabase {
|
||||
return {
|
||||
...omit(profile, ['allowedMembers', 'scheduleDaysEnabled']),
|
||||
emoji: profile.emoji || null,
|
||||
allowAllCalls: profile.allowAllCalls ? 1 : 0,
|
||||
allowAllMentions: profile.allowAllMentions ? 1 : 0,
|
||||
scheduleEnabled: profile.scheduleEnabled ? 1 : 0,
|
||||
allowedMembersJson: profile.allowedMembers
|
||||
? JSON.stringify(Array.from(profile.allowedMembers))
|
||||
: null,
|
||||
scheduleStartTime: profile.scheduleStartTime || null,
|
||||
scheduleEndTime: profile.scheduleEndTime || null,
|
||||
scheduleDaysEnabledJson: profile.scheduleDaysEnabled
|
||||
? JSON.stringify(profile.scheduleDaysEnabled)
|
||||
: null,
|
||||
deletedAtTimestampMs: profile.deletedAtTimestampMs || null,
|
||||
storageID: profile.storageID || null,
|
||||
storageVersion: profile.storageVersion || null,
|
||||
storageNeedsSync: profile.storageNeedsSync ? 1 : 0,
|
||||
storageUnknownFields: profile.storageUnknownFields || null,
|
||||
};
|
||||
}
|
||||
|
||||
function getAllNotificationProfiles(
|
||||
db: ReadableDB
|
||||
): Array<NotificationProfileType> {
|
||||
const notificationProfiles = db
|
||||
.prepare('SELECT * FROM notificationProfiles ORDER BY createdAtMs DESC;')
|
||||
.all<NotificationProfileForDatabase>();
|
||||
|
||||
return notificationProfiles.map(hydrateNotificationProfile);
|
||||
}
|
||||
function getNotificationProfileById(
|
||||
db: ReadableDB,
|
||||
id: string
|
||||
): NotificationProfileType | undefined {
|
||||
const [query, parameters] =
|
||||
sql`SELECT * FROM notificationProfiles WHERE id = ${id}`;
|
||||
const fromDatabase = db
|
||||
.prepare(query)
|
||||
.get<NotificationProfileForDatabase>(parameters);
|
||||
|
||||
if (fromDatabase) {
|
||||
return hydrateNotificationProfile(fromDatabase);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
function _deleteAllNotificationProfiles(db: WritableDB): void {
|
||||
db.prepare('DELETE FROM notificationProfiles;').run();
|
||||
}
|
||||
function deleteNotificationProfileById(db: WritableDB, id: string): void {
|
||||
const [query, parameters] =
|
||||
sql`DELETE FROM notificationProfiles WHERE id = ${id}`;
|
||||
db.prepare(query).run(parameters);
|
||||
}
|
||||
function markNotificationProfileDeleted(
|
||||
db: WritableDB,
|
||||
id: string
|
||||
): number | undefined {
|
||||
const now = new Date().getTime();
|
||||
|
||||
const [query, parameters] = sql`
|
||||
UPDATE notificationProfiles
|
||||
SET deletedAtTimestampMs = ${now}
|
||||
WHERE
|
||||
id = ${id} AND
|
||||
deletedAtTimestampMs IS NULL
|
||||
RETURNING deletedAtTimestampMs`;
|
||||
|
||||
const record = db
|
||||
.prepare(query)
|
||||
.get<{ deletedAtTimestampMs: number }>(parameters);
|
||||
|
||||
return record?.deletedAtTimestampMs;
|
||||
}
|
||||
function createNotificationProfile(
|
||||
db: WritableDB,
|
||||
profile: NotificationProfileType
|
||||
): void {
|
||||
strictAssert(profile.name, 'Notification profile does not have a valid name');
|
||||
|
||||
const forDatabase = freezeNotificationProfile(profile);
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
INSERT INTO notificationProfiles(
|
||||
id,
|
||||
name,
|
||||
emoji,
|
||||
color,
|
||||
createdAtMs,
|
||||
allowAllCalls,
|
||||
allowAllMentions,
|
||||
allowedMembersJson,
|
||||
scheduleEnabled,
|
||||
scheduleStartTime,
|
||||
scheduleEndTime,
|
||||
scheduleDaysEnabledJson,
|
||||
deletedAtTimestampMs,
|
||||
storageID,
|
||||
storageVersion,
|
||||
storageUnknownFields,
|
||||
storageNeedsSync
|
||||
) VALUES (
|
||||
$id,
|
||||
$name,
|
||||
$emoji,
|
||||
$color,
|
||||
$createdAtMs,
|
||||
$allowAllCalls,
|
||||
$allowAllMentions,
|
||||
$allowedMembersJson,
|
||||
$scheduleEnabled,
|
||||
$scheduleStartTime,
|
||||
$scheduleEndTime,
|
||||
$scheduleDaysEnabledJson,
|
||||
$deletedAtTimestampMs,
|
||||
$storageID,
|
||||
$storageVersion,
|
||||
$storageUnknownFields,
|
||||
$storageNeedsSync
|
||||
);
|
||||
`
|
||||
).run(forDatabase);
|
||||
}
|
||||
function updateNotificationProfile(
|
||||
db: WritableDB,
|
||||
profile: NotificationProfileType
|
||||
): void {
|
||||
strictAssert(profile.name, 'Notification profile does not have a valid name');
|
||||
|
||||
db.transaction(() => {
|
||||
const forDatabase = freezeNotificationProfile(profile);
|
||||
|
||||
db.prepare(
|
||||
`
|
||||
UPDATE notificationProfiles SET
|
||||
name = $name,
|
||||
emoji = $emoji,
|
||||
color = $color,
|
||||
createdAtMs = $createdAtMs,
|
||||
allowAllCalls = $allowAllCalls,
|
||||
allowAllMentions = $allowAllMentions,
|
||||
allowedMembersJson = $allowedMembersJson,
|
||||
scheduleEnabled = $scheduleEnabled,
|
||||
scheduleStartTime = $scheduleStartTime,
|
||||
scheduleEndTime = $scheduleEndTime,
|
||||
scheduleDaysEnabledJson = $scheduleDaysEnabledJson,
|
||||
deletedAtTimestampMs = $deletedAtTimestampMs,
|
||||
storageID = $storageID,
|
||||
storageVersion = $storageVersion,
|
||||
storageUnknownFields = $storageUnknownFields,
|
||||
storageNeedsSync = $storageNeedsSync
|
||||
WHERE
|
||||
id = $id;
|
||||
`
|
||||
).run(forDatabase);
|
||||
})();
|
||||
}
|
||||
|
||||
// All data in database
|
||||
function removeAll(db: WritableDB): void {
|
||||
db.transaction(() => {
|
||||
@@ -6885,6 +7113,7 @@ function removeAll(db: WritableDB): void {
|
||||
DELETE FROM kyberPreKeys;
|
||||
DELETE FROM messages_fts;
|
||||
DELETE FROM messages;
|
||||
DELETE FROM notificationProfiles;
|
||||
DELETE FROM preKeys;
|
||||
DELETE FROM reactions;
|
||||
DELETE FROM senderKeys;
|
||||
|
||||
Reference in New Issue
Block a user