mirror of
https://github.com/binwiederhier/ntfy.git
synced 2026-01-18 16:17:26 +01:00
Remove mtime
This commit is contained in:
@@ -31,7 +31,6 @@ const (
|
||||
mid TEXT NOT NULL,
|
||||
sid TEXT NOT NULL,
|
||||
time INT NOT NULL,
|
||||
mtime INT NOT NULL,
|
||||
expires INT NOT NULL,
|
||||
topic TEXT NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
@@ -57,7 +56,6 @@ const (
|
||||
CREATE INDEX IF NOT EXISTS idx_mid ON messages (mid);
|
||||
CREATE INDEX IF NOT EXISTS idx_sid ON messages (sid);
|
||||
CREATE INDEX IF NOT EXISTS idx_time ON messages (time);
|
||||
CREATE INDEX IF NOT EXISTS idx_mtime ON messages (mtime);
|
||||
CREATE INDEX IF NOT EXISTS idx_topic ON messages (topic);
|
||||
CREATE INDEX IF NOT EXISTS idx_expires ON messages (expires);
|
||||
CREATE INDEX IF NOT EXISTS idx_sender ON messages (sender);
|
||||
@@ -71,53 +69,53 @@ const (
|
||||
COMMIT;
|
||||
`
|
||||
insertMessageQuery = `
|
||||
INSERT INTO messages (mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, attachment_deleted, sender, user, content_type, encoding, published, deleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO messages (mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, attachment_deleted, sender, user, content_type, encoding, published, deleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`
|
||||
deleteMessageQuery = `DELETE FROM messages WHERE mid = ?`
|
||||
updateMessagesForTopicExpiryQuery = `UPDATE messages SET expires = ? WHERE topic = ?`
|
||||
selectRowIDFromMessageID = `SELECT id FROM messages WHERE mid = ?` // Do not include topic, see #336 and TestServer_PollSinceID_MultipleTopics
|
||||
selectMessagesByIDQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE mid = ?
|
||||
`
|
||||
selectMessagesSinceTimeQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE topic = ? AND time >= ? AND published = 1
|
||||
ORDER BY mtime, id
|
||||
ORDER BY time, id
|
||||
`
|
||||
selectMessagesSinceTimeIncludeScheduledQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE topic = ? AND time >= ?
|
||||
ORDER BY mtime, id
|
||||
ORDER BY time, id
|
||||
`
|
||||
selectMessagesSinceIDQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE topic = ? AND id > ? AND published = 1
|
||||
ORDER BY mtime, id
|
||||
ORDER BY time, id
|
||||
`
|
||||
selectMessagesSinceIDIncludeScheduledQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE topic = ? AND (id > ? OR published = 0)
|
||||
ORDER BY mtime, id
|
||||
ORDER BY time, id
|
||||
`
|
||||
selectMessagesLatestQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE topic = ? AND published = 1
|
||||
ORDER BY time DESC, id DESC
|
||||
LIMIT 1
|
||||
`
|
||||
selectMessagesDueQuery = `
|
||||
SELECT mid, sid, time, mtime, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
SELECT mid, sid, time, expires, topic, message, title, priority, tags, click, icon, actions, attachment_name, attachment_type, attachment_size, attachment_expires, attachment_url, sender, user, content_type, encoding, deleted
|
||||
FROM messages
|
||||
WHERE time <= ? AND published = 0
|
||||
ORDER BY mtime, id
|
||||
ORDER BY time, id
|
||||
`
|
||||
selectMessagesExpiredQuery = `SELECT mid FROM messages WHERE expires <= ? AND published = 1`
|
||||
updateMessagePublishedQuery = `UPDATE messages SET published = 1 WHERE mid = ?`
|
||||
@@ -270,10 +268,8 @@ const (
|
||||
//13 -> 14
|
||||
migrate13To14AlterMessagesTableQuery = `
|
||||
ALTER TABLE messages ADD COLUMN sid TEXT NOT NULL DEFAULT('');
|
||||
ALTER TABLE messages ADD COLUMN mtime INT NOT NULL DEFAULT('0');
|
||||
ALTER TABLE messages ADD COLUMN deleted INT NOT NULL DEFAULT('0');
|
||||
CREATE INDEX IF NOT EXISTS idx_sid ON messages (sid);
|
||||
CREATE INDEX IF NOT EXISTS idx_mtime ON messages (mtime);
|
||||
`
|
||||
)
|
||||
|
||||
@@ -415,7 +411,6 @@ func (c *messageCache) addMessages(ms []*message) error {
|
||||
m.ID,
|
||||
m.SID,
|
||||
m.Time,
|
||||
m.MTime,
|
||||
m.Expires,
|
||||
m.Topic,
|
||||
m.Message,
|
||||
@@ -723,14 +718,13 @@ func readMessages(rows *sql.Rows) ([]*message, error) {
|
||||
}
|
||||
|
||||
func readMessage(rows *sql.Rows) (*message, error) {
|
||||
var timestamp, mtimestamp, expires, attachmentSize, attachmentExpires int64
|
||||
var timestamp, expires, attachmentSize, attachmentExpires int64
|
||||
var priority, deleted int
|
||||
var id, sid, topic, msg, title, tagsStr, click, icon, actionsStr, attachmentName, attachmentType, attachmentURL, sender, user, contentType, encoding string
|
||||
err := rows.Scan(
|
||||
&id,
|
||||
&sid,
|
||||
×tamp,
|
||||
&mtimestamp,
|
||||
&expires,
|
||||
&topic,
|
||||
&msg,
|
||||
@@ -782,7 +776,6 @@ func readMessage(rows *sql.Rows) (*message, error) {
|
||||
ID: id,
|
||||
SID: sid,
|
||||
Time: timestamp,
|
||||
MTime: mtimestamp,
|
||||
Expires: expires,
|
||||
Event: messageEvent,
|
||||
Topic: topic,
|
||||
|
||||
@@ -24,11 +24,9 @@ func TestMemCache_Messages(t *testing.T) {
|
||||
func testCacheMessages(t *testing.T, c *messageCache) {
|
||||
m1 := newDefaultMessage("mytopic", "my message")
|
||||
m1.Time = 1
|
||||
m1.MTime = 1000
|
||||
|
||||
m2 := newDefaultMessage("mytopic", "my other message")
|
||||
m2.Time = 2
|
||||
m2.MTime = 2000
|
||||
|
||||
require.Nil(t, c.AddMessage(m1))
|
||||
require.Nil(t, c.AddMessage(newDefaultMessage("example", "my example message")))
|
||||
@@ -126,13 +124,10 @@ func testCacheMessagesScheduled(t *testing.T, c *messageCache) {
|
||||
m1 := newDefaultMessage("mytopic", "message 1")
|
||||
m2 := newDefaultMessage("mytopic", "message 2")
|
||||
m2.Time = time.Now().Add(time.Hour).Unix()
|
||||
m2.MTime = time.Now().Add(time.Hour).UnixMilli()
|
||||
m3 := newDefaultMessage("mytopic", "message 3")
|
||||
m3.Time = time.Now().Add(time.Minute).Unix() // earlier than m2!
|
||||
m3.MTime = time.Now().Add(time.Minute).UnixMilli() // earlier than m2!
|
||||
m3.Time = time.Now().Add(time.Minute).Unix() // earlier than m2!
|
||||
m4 := newDefaultMessage("mytopic2", "message 4")
|
||||
m4.Time = time.Now().Add(time.Minute).Unix()
|
||||
m4.MTime = time.Now().Add(time.Minute).UnixMilli()
|
||||
require.Nil(t, c.AddMessage(m1))
|
||||
require.Nil(t, c.AddMessage(m2))
|
||||
require.Nil(t, c.AddMessage(m3))
|
||||
@@ -206,25 +201,18 @@ func TestMemCache_MessagesSinceID(t *testing.T) {
|
||||
func testCacheMessagesSinceID(t *testing.T, c *messageCache) {
|
||||
m1 := newDefaultMessage("mytopic", "message 1")
|
||||
m1.Time = 100
|
||||
m1.MTime = 100000
|
||||
m2 := newDefaultMessage("mytopic", "message 2")
|
||||
m2.Time = 200
|
||||
m2.MTime = 200000
|
||||
m3 := newDefaultMessage("mytopic", "message 3")
|
||||
m3.Time = time.Now().Add(time.Hour).Unix() // Scheduled, in the future, later than m7 and m5
|
||||
m3.MTime = time.Now().Add(time.Hour).UnixMilli() // Scheduled, in the future, later than m7 and m5
|
||||
m3.Time = time.Now().Add(time.Hour).Unix() // Scheduled, in the future, later than m7 and m5
|
||||
m4 := newDefaultMessage("mytopic", "message 4")
|
||||
m4.Time = 400
|
||||
m4.MTime = 400000
|
||||
m5 := newDefaultMessage("mytopic", "message 5")
|
||||
m5.Time = time.Now().Add(time.Minute).Unix() // Scheduled, in the future, later than m7
|
||||
m5.MTime = time.Now().Add(time.Minute).UnixMilli() // Scheduled, in the future, later than m7
|
||||
m5.Time = time.Now().Add(time.Minute).Unix() // Scheduled, in the future, later than m7
|
||||
m6 := newDefaultMessage("mytopic", "message 6")
|
||||
m6.Time = 600
|
||||
m6.MTime = 600000
|
||||
m7 := newDefaultMessage("mytopic", "message 7")
|
||||
m7.Time = 700
|
||||
m7.MTime = 700000
|
||||
|
||||
require.Nil(t, c.AddMessage(m1))
|
||||
require.Nil(t, c.AddMessage(m2))
|
||||
@@ -285,17 +273,14 @@ func testCachePrune(t *testing.T, c *messageCache) {
|
||||
|
||||
m1 := newDefaultMessage("mytopic", "my message")
|
||||
m1.Time = now - 10
|
||||
m1.MTime = (now - 10) * 1000
|
||||
m1.Expires = now - 5
|
||||
|
||||
m2 := newDefaultMessage("mytopic", "my other message")
|
||||
m2.Time = now - 5
|
||||
m2.MTime = (now - 5) * 1000
|
||||
m2.Expires = now + 5 // In the future
|
||||
|
||||
m3 := newDefaultMessage("another_topic", "and another one")
|
||||
m3.Time = now - 12
|
||||
m3.MTime = (now - 12) * 1000
|
||||
m3.Expires = now - 2
|
||||
|
||||
require.Nil(t, c.AddMessage(m1))
|
||||
@@ -546,7 +531,6 @@ func TestSqliteCache_Migration_From1(t *testing.T) {
|
||||
// Add delayed message
|
||||
delayedMessage := newDefaultMessage("mytopic", "some delayed message")
|
||||
delayedMessage.Time = time.Now().Add(time.Minute).Unix()
|
||||
delayedMessage.MTime = time.Now().Add(time.Minute).UnixMilli()
|
||||
require.Nil(t, c.AddMessage(delayedMessage))
|
||||
|
||||
// 10, not 11!
|
||||
|
||||
@@ -874,7 +874,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visito
|
||||
return err
|
||||
}
|
||||
minc(metricMessagesPublishedSuccess)
|
||||
return s.writeJSON(w, m)
|
||||
return s.writeJSON(w, m.forJSON())
|
||||
}
|
||||
|
||||
func (s *Server) handlePublishMatrix(w http.ResponseWriter, r *http.Request, v *visitor) error {
|
||||
@@ -1291,7 +1291,7 @@ func (s *Server) handleBodyAsAttachment(r *http.Request, v *visitor, m *message,
|
||||
func (s *Server) handleSubscribeJSON(w http.ResponseWriter, r *http.Request, v *visitor) error {
|
||||
encoder := func(msg *message) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(&msg); err != nil {
|
||||
if err := json.NewEncoder(&buf).Encode(msg.forJSON()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
@@ -1302,7 +1302,7 @@ func (s *Server) handleSubscribeJSON(w http.ResponseWriter, r *http.Request, v *
|
||||
func (s *Server) handleSubscribeSSE(w http.ResponseWriter, r *http.Request, v *visitor) error {
|
||||
encoder := func(msg *message) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := json.NewEncoder(&buf).Encode(&msg); err != nil {
|
||||
if err := json.NewEncoder(&buf).Encode(msg.forJSON()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if msg.Event != messageEvent {
|
||||
|
||||
@@ -24,10 +24,9 @@ const (
|
||||
|
||||
// message represents a message published to a topic
|
||||
type message struct {
|
||||
ID string `json:"id"` // Random message ID
|
||||
SID string `json:"sid"` // Message sequence ID for updating message contents
|
||||
Time int64 `json:"time"` // Unix time in seconds
|
||||
MTime int64 `json:"mtime"` // Unix time in milliseconds
|
||||
ID string `json:"id"` // Random message ID
|
||||
SID string `json:"sid,omitempty"` // Message sequence ID for updating message contents (omitted if same as ID)
|
||||
Time int64 `json:"time"` // Unix time in seconds
|
||||
Expires int64 `json:"expires,omitempty"` // Unix time in seconds (not required for open/keepalive)
|
||||
Event string `json:"event"` // One of the above
|
||||
Topic string `json:"topic"`
|
||||
@@ -53,7 +52,6 @@ func (m *message) Context() log.Context {
|
||||
"message_id": m.ID,
|
||||
"message_sid": m.SID,
|
||||
"message_time": m.Time,
|
||||
"message_mtime": m.MTime,
|
||||
"message_event": m.Event,
|
||||
"message_body_size": len(m.Message),
|
||||
}
|
||||
@@ -66,6 +64,16 @@ func (m *message) Context() log.Context {
|
||||
return fields
|
||||
}
|
||||
|
||||
// forJSON returns a copy of the message prepared for JSON output.
|
||||
// It clears SID if it equals ID (to avoid redundant output).
|
||||
func (m *message) forJSON() *message {
|
||||
msg := *m
|
||||
if msg.SID == msg.ID {
|
||||
msg.SID = "" // Will be omitted due to omitempty
|
||||
}
|
||||
return &msg
|
||||
}
|
||||
|
||||
type attachment struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type,omitempty"`
|
||||
@@ -123,7 +131,6 @@ func newMessage(event, topic, msg string) *message {
|
||||
return &message{
|
||||
ID: util.RandomString(messageIDLength),
|
||||
Time: time.Now().Unix(),
|
||||
MTime: time.Now().UnixMilli(),
|
||||
Event: event,
|
||||
Topic: topic,
|
||||
Message: msg,
|
||||
@@ -162,11 +169,7 @@ type sinceMarker struct {
|
||||
}
|
||||
|
||||
func newSinceTime(timestamp int64) sinceMarker {
|
||||
return newSinceMTime(timestamp * 1000)
|
||||
}
|
||||
|
||||
func newSinceMTime(mtimestamp int64) sinceMarker {
|
||||
return sinceMarker{time.UnixMilli(mtimestamp), ""}
|
||||
return sinceMarker{time.Unix(timestamp, 0), ""}
|
||||
}
|
||||
|
||||
func newSinceID(id string) sinceMarker {
|
||||
@@ -557,7 +560,7 @@ func newWebPushPayload(subscriptionID string, message *message) *webPushPayload
|
||||
return &webPushPayload{
|
||||
Event: webPushMessageEvent,
|
||||
SubscriptionID: subscriptionID,
|
||||
Message: message,
|
||||
Message: message.forJSON(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@
|
||||
"notifications_delete": "Delete",
|
||||
"notifications_copied_to_clipboard": "Copied to clipboard",
|
||||
"notifications_tags": "Tags",
|
||||
"notifications_sid": "Sequence ID",
|
||||
"notifications_revisions": "Revisions",
|
||||
"notifications_modified": "modified {{date}}",
|
||||
"notifications_priority_x": "Priority {{priority}}",
|
||||
"notifications_new_indicator": "New notification",
|
||||
"notifications_attachment_image": "Attachment image",
|
||||
|
||||
@@ -25,9 +25,6 @@ const addNotification = async ({ subscriptionId, message }) => {
|
||||
const db = await dbAsync();
|
||||
const populatedMessage = message;
|
||||
|
||||
if (!("mtime" in populatedMessage)) {
|
||||
populatedMessage.mtime = message.time * 1000;
|
||||
}
|
||||
if (!("sid" in populatedMessage)) {
|
||||
populatedMessage.sid = message.id;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ class SubscriptionManager {
|
||||
// killing performance. See https://dexie.org/docs/Collection/Collection.offset()#a-better-paging-approach
|
||||
|
||||
const notifications = await this.db.notifications
|
||||
.orderBy("mtime") // Sort by time first
|
||||
.orderBy("time") // Sort by time
|
||||
.filter((n) => n.subscriptionId === subscriptionId)
|
||||
.reverse()
|
||||
.toArray();
|
||||
@@ -167,30 +167,39 @@ class SubscriptionManager {
|
||||
|
||||
async getAllNotifications() {
|
||||
const notifications = await this.db.notifications
|
||||
.orderBy("mtime") // Efficient, see docs
|
||||
.orderBy("time") // Efficient, see docs
|
||||
.reverse()
|
||||
.toArray();
|
||||
|
||||
return this.groupNotificationsBySID(notifications);
|
||||
}
|
||||
|
||||
// Collapse notification updates based on sids
|
||||
// Collapse notification updates based on sids, keeping only the latest version
|
||||
// Also tracks the original time (earliest) for each sequence
|
||||
groupNotificationsBySID(notifications) {
|
||||
const results = {};
|
||||
const latestBySid = {};
|
||||
const originalTimeBySid = {};
|
||||
|
||||
notifications.forEach((notification) => {
|
||||
const key = `${notification.subscriptionId}:${notification.sid}`;
|
||||
if (key in results) {
|
||||
if ("history" in results[key]) {
|
||||
results[key].history.push(notification);
|
||||
} else {
|
||||
results[key].history = [notification];
|
||||
}
|
||||
} else {
|
||||
results[key] = notification;
|
||||
|
||||
// Track the latest notification for each sid (first one since sorted DESC)
|
||||
if (!(key in latestBySid)) {
|
||||
latestBySid[key] = notification;
|
||||
}
|
||||
|
||||
// Track the original (earliest) time for each sid
|
||||
const currentOriginal = originalTimeBySid[key];
|
||||
if (currentOriginal === undefined || notification.time < currentOriginal) {
|
||||
originalTimeBySid[key] = notification.time;
|
||||
}
|
||||
});
|
||||
|
||||
return Object.values(results);
|
||||
// Return latest notifications with originalTime set
|
||||
return Object.entries(latestBySid).map(([key, notification]) => ({
|
||||
...notification,
|
||||
originalTime: originalTimeBySid[key],
|
||||
}));
|
||||
}
|
||||
|
||||
/** Adds notification, or returns false if it already exists */
|
||||
@@ -201,9 +210,6 @@ class SubscriptionManager {
|
||||
}
|
||||
try {
|
||||
const populatedNotification = notification;
|
||||
if (!("mtime" in populatedNotification)) {
|
||||
populatedNotification.mtime = notification.time * 1000;
|
||||
}
|
||||
if (!("sid" in populatedNotification)) {
|
||||
populatedNotification.sid = notification.id;
|
||||
}
|
||||
@@ -227,9 +233,6 @@ class SubscriptionManager {
|
||||
async addNotifications(subscriptionId, notifications) {
|
||||
const notificationsWithSubscriptionId = notifications.map((notification) => {
|
||||
const populatedNotification = notification;
|
||||
if (!("mtime" in populatedNotification)) {
|
||||
populatedNotification.mtime = notification.time * 1000;
|
||||
}
|
||||
if (!("sid" in populatedNotification)) {
|
||||
populatedNotification.sid = notification.id;
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ const createDatabase = (username) => {
|
||||
const dbName = username ? `ntfy-${username}` : "ntfy"; // IndexedDB database is based on the logged-in user
|
||||
const db = new Dexie(dbName);
|
||||
|
||||
db.version(3).stores({
|
||||
db.version(4).stores({
|
||||
subscriptions: "&id,baseUrl,[baseUrl+mutedUntil]",
|
||||
notifications: "&id,sid,subscriptionId,time,mtime,new,[subscriptionId+new]", // compound key for query performance
|
||||
notifications: "&id,sid,subscriptionId,time,new,[subscriptionId+new]", // compound key for query performance
|
||||
users: "&baseUrl,username",
|
||||
prefs: "&key",
|
||||
});
|
||||
|
||||
@@ -69,7 +69,7 @@ export const toNotificationParams = ({ subscriptionId, message, defaultTitle, to
|
||||
badge,
|
||||
icon,
|
||||
image,
|
||||
timestamp: message.mtime,
|
||||
timestamp: message.time * 1000,
|
||||
tag,
|
||||
renotify: true,
|
||||
silent: false,
|
||||
|
||||
@@ -236,7 +236,9 @@ const NotificationItem = (props) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { notification } = props;
|
||||
const { attachment } = notification;
|
||||
const date = formatShortDateTime(notification.time, i18n.language);
|
||||
const isModified = notification.originalTime && notification.originalTime !== notification.time;
|
||||
const originalDate = formatShortDateTime(notification.originalTime || notification.time, i18n.language);
|
||||
const modifiedDate = isModified ? formatShortDateTime(notification.time, i18n.language) : null;
|
||||
const otherTags = unmatchedTags(notification.tags);
|
||||
const tags = otherTags.length > 0 ? otherTags.join(", ") : null;
|
||||
const handleDelete = async () => {
|
||||
@@ -267,8 +269,6 @@ const NotificationItem = (props) => {
|
||||
const hasUserActions = notification.actions && notification.actions.length > 0;
|
||||
const showActions = hasAttachmentActions || hasClickAction || hasUserActions;
|
||||
|
||||
const showSid = notification.id !== notification.sid || notification.history;
|
||||
|
||||
return (
|
||||
<Card sx={{ padding: 1 }} role="listitem" aria-label={t("notifications_list_item")}>
|
||||
<CardContent>
|
||||
@@ -289,7 +289,8 @@ const NotificationItem = (props) => {
|
||||
</Tooltip>
|
||||
)}
|
||||
<Typography sx={{ fontSize: 14 }} color="text.secondary">
|
||||
{date}
|
||||
{originalDate}
|
||||
{modifiedDate && ` (${t("notifications_modified", { date: modifiedDate })})`}
|
||||
{[1, 2, 4, 5].includes(notification.priority) && (
|
||||
<img
|
||||
src={priorityFiles[notification.priority]}
|
||||
@@ -325,16 +326,6 @@ const NotificationItem = (props) => {
|
||||
{t("notifications_tags")}: {tags}
|
||||
</Typography>
|
||||
)}
|
||||
{showSid && (
|
||||
<Typography sx={{ fontSize: 14 }} color="text.secondary">
|
||||
{t("notifications_sid")}: {notification.sid}
|
||||
</Typography>
|
||||
)}
|
||||
{notification.history && (
|
||||
<Typography sx={{ fontSize: 14 }} color="text.secondary">
|
||||
{t("notifications_revisions")}: {notification.history.length + 1}
|
||||
</Typography>
|
||||
)}
|
||||
</CardContent>
|
||||
{showActions && (
|
||||
<CardActions sx={{ paddingTop: 0 }}>
|
||||
|
||||
Reference in New Issue
Block a user