Add support for moderation report notifications (#2887)
* Add support for moderation report notifications * Translate report categories * Apply tint inside flag drawable * Remove unused imports Co-authored-by: Konrad Pozniak <connyduck@users.noreply.github.com>
This commit is contained in:
		
					parent
					
						
							
								86e5c92a05
							
						
					
				
			
			
				commit
				
					
						6b95790457
					
				
			
		
					 18 changed files with 1257 additions and 11 deletions
				
			
		
							
								
								
									
										965
									
								
								app/schemas/com.keylesspalace.tusky.db.AppDatabase/44.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										965
									
								
								app/schemas/com.keylesspalace.tusky.db.AppDatabase/44.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,965 @@ | |||
| { | ||||
|   "formatVersion": 1, | ||||
|   "database": { | ||||
|     "version": 44, | ||||
|     "identityHash": "7b5271980102f35e55438f46777e3d46", | ||||
|     "entities": [ | ||||
|       { | ||||
|         "tableName": "DraftEntity", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountId` INTEGER NOT NULL, `inReplyToId` TEXT, `content` TEXT, `contentWarning` TEXT, `sensitive` INTEGER NOT NULL, `visibility` INTEGER NOT NULL, `attachments` TEXT NOT NULL, `poll` TEXT, `failedToSend` INTEGER NOT NULL, `scheduledAt` TEXT, `language` TEXT)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "id", | ||||
|             "columnName": "id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "accountId", | ||||
|             "columnName": "accountId", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "inReplyToId", | ||||
|             "columnName": "inReplyToId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "content", | ||||
|             "columnName": "content", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "contentWarning", | ||||
|             "columnName": "contentWarning", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "sensitive", | ||||
|             "columnName": "sensitive", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "visibility", | ||||
|             "columnName": "visibility", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "attachments", | ||||
|             "columnName": "attachments", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "poll", | ||||
|             "columnName": "poll", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "failedToSend", | ||||
|             "columnName": "failedToSend", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "scheduledAt", | ||||
|             "columnName": "scheduledAt", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "language", | ||||
|             "columnName": "language", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "columnNames": [ | ||||
|             "id" | ||||
|           ], | ||||
|           "autoGenerate": true | ||||
|         }, | ||||
|         "indices": [], | ||||
|         "foreignKeys": [] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "AccountEntity", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `clientId` TEXT, `clientSecret` TEXT, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `notificationsEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsFollowRequested` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationsPolls` INTEGER NOT NULL, `notificationsSubscriptions` INTEGER NOT NULL, `notificationsSignUps` INTEGER NOT NULL, `notificationsUpdates` INTEGER NOT NULL, `notificationsReports` INTEGER NOT NULL, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `defaultPostLanguage` TEXT NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `alwaysOpenSpoiler` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `lastNotificationId` TEXT NOT NULL, `activeNotifications` TEXT NOT NULL, `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL, `notificationsFilter` TEXT NOT NULL, `oauthScopes` TEXT NOT NULL, `unifiedPushUrl` TEXT NOT NULL, `pushPubKey` TEXT NOT NULL, `pushPrivKey` TEXT NOT NULL, `pushAuth` TEXT NOT NULL, `pushServerKey` TEXT NOT NULL)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "id", | ||||
|             "columnName": "id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "domain", | ||||
|             "columnName": "domain", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "accessToken", | ||||
|             "columnName": "accessToken", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "clientId", | ||||
|             "columnName": "clientId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "clientSecret", | ||||
|             "columnName": "clientSecret", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "isActive", | ||||
|             "columnName": "isActive", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "accountId", | ||||
|             "columnName": "accountId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "username", | ||||
|             "columnName": "username", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "displayName", | ||||
|             "columnName": "displayName", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "profilePictureUrl", | ||||
|             "columnName": "profilePictureUrl", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsEnabled", | ||||
|             "columnName": "notificationsEnabled", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsMentioned", | ||||
|             "columnName": "notificationsMentioned", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsFollowed", | ||||
|             "columnName": "notificationsFollowed", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsFollowRequested", | ||||
|             "columnName": "notificationsFollowRequested", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsReblogged", | ||||
|             "columnName": "notificationsReblogged", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsFavorited", | ||||
|             "columnName": "notificationsFavorited", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsPolls", | ||||
|             "columnName": "notificationsPolls", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsSubscriptions", | ||||
|             "columnName": "notificationsSubscriptions", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsSignUps", | ||||
|             "columnName": "notificationsSignUps", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsUpdates", | ||||
|             "columnName": "notificationsUpdates", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsReports", | ||||
|             "columnName": "notificationsReports", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationSound", | ||||
|             "columnName": "notificationSound", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationVibration", | ||||
|             "columnName": "notificationVibration", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationLight", | ||||
|             "columnName": "notificationLight", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "defaultPostPrivacy", | ||||
|             "columnName": "defaultPostPrivacy", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "defaultMediaSensitivity", | ||||
|             "columnName": "defaultMediaSensitivity", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "defaultPostLanguage", | ||||
|             "columnName": "defaultPostLanguage", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "alwaysShowSensitiveMedia", | ||||
|             "columnName": "alwaysShowSensitiveMedia", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "alwaysOpenSpoiler", | ||||
|             "columnName": "alwaysOpenSpoiler", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "mediaPreviewEnabled", | ||||
|             "columnName": "mediaPreviewEnabled", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastNotificationId", | ||||
|             "columnName": "lastNotificationId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "activeNotifications", | ||||
|             "columnName": "activeNotifications", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "emojis", | ||||
|             "columnName": "emojis", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "tabPreferences", | ||||
|             "columnName": "tabPreferences", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationsFilter", | ||||
|             "columnName": "notificationsFilter", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "oauthScopes", | ||||
|             "columnName": "oauthScopes", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "unifiedPushUrl", | ||||
|             "columnName": "unifiedPushUrl", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "pushPubKey", | ||||
|             "columnName": "pushPubKey", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "pushPrivKey", | ||||
|             "columnName": "pushPrivKey", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "pushAuth", | ||||
|             "columnName": "pushAuth", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "pushServerKey", | ||||
|             "columnName": "pushServerKey", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "columnNames": [ | ||||
|             "id" | ||||
|           ], | ||||
|           "autoGenerate": true | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_AccountEntity_domain_accountId", | ||||
|             "unique": true, | ||||
|             "columnNames": [ | ||||
|               "domain", | ||||
|               "accountId" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_AccountEntity_domain_accountId` ON `${TABLE_NAME}` (`domain`, `accountId`)" | ||||
|           } | ||||
|         ], | ||||
|         "foreignKeys": [] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "InstanceEntity", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`instance` TEXT NOT NULL, `emojiList` TEXT, `maximumTootCharacters` INTEGER, `maxPollOptions` INTEGER, `maxPollOptionLength` INTEGER, `minPollDuration` INTEGER, `maxPollDuration` INTEGER, `charactersReservedPerUrl` INTEGER, `version` TEXT, `videoSizeLimit` INTEGER, `imageSizeLimit` INTEGER, `imageMatrixLimit` INTEGER, `maxMediaAttachments` INTEGER, `maxFields` INTEGER, `maxFieldNameLength` INTEGER, `maxFieldValueLength` INTEGER, PRIMARY KEY(`instance`))", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "instance", | ||||
|             "columnName": "instance", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "emojiList", | ||||
|             "columnName": "emojiList", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maximumTootCharacters", | ||||
|             "columnName": "maximumTootCharacters", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxPollOptions", | ||||
|             "columnName": "maxPollOptions", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxPollOptionLength", | ||||
|             "columnName": "maxPollOptionLength", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "minPollDuration", | ||||
|             "columnName": "minPollDuration", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxPollDuration", | ||||
|             "columnName": "maxPollDuration", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "charactersReservedPerUrl", | ||||
|             "columnName": "charactersReservedPerUrl", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "version", | ||||
|             "columnName": "version", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "videoSizeLimit", | ||||
|             "columnName": "videoSizeLimit", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "imageSizeLimit", | ||||
|             "columnName": "imageSizeLimit", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "imageMatrixLimit", | ||||
|             "columnName": "imageMatrixLimit", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxMediaAttachments", | ||||
|             "columnName": "maxMediaAttachments", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxFields", | ||||
|             "columnName": "maxFields", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxFieldNameLength", | ||||
|             "columnName": "maxFieldNameLength", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "maxFieldValueLength", | ||||
|             "columnName": "maxFieldValueLength", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "columnNames": [ | ||||
|             "instance" | ||||
|           ], | ||||
|           "autoGenerate": false | ||||
|         }, | ||||
|         "indices": [], | ||||
|         "foreignKeys": [] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "TimelineStatusEntity", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `url` TEXT, `timelineUserId` INTEGER NOT NULL, `authorServerId` TEXT, `inReplyToId` TEXT, `inReplyToAccountId` TEXT, `content` TEXT, `createdAt` INTEGER NOT NULL, `emojis` TEXT, `reblogsCount` INTEGER NOT NULL, `favouritesCount` INTEGER NOT NULL, `repliesCount` INTEGER NOT NULL, `reblogged` INTEGER NOT NULL, `bookmarked` INTEGER NOT NULL, `favourited` INTEGER NOT NULL, `sensitive` INTEGER NOT NULL, `spoilerText` TEXT NOT NULL, `visibility` INTEGER NOT NULL, `attachments` TEXT, `mentions` TEXT, `tags` TEXT, `application` TEXT, `reblogServerId` TEXT, `reblogAccountId` TEXT, `poll` TEXT, `muted` INTEGER, `expanded` INTEGER NOT NULL, `contentCollapsed` INTEGER NOT NULL, `contentShowing` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `card` TEXT, `language` TEXT, PRIMARY KEY(`serverId`, `timelineUserId`), FOREIGN KEY(`authorServerId`, `timelineUserId`) REFERENCES `TimelineAccountEntity`(`serverId`, `timelineUserId`) ON UPDATE NO ACTION ON DELETE NO ACTION )", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "serverId", | ||||
|             "columnName": "serverId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "url", | ||||
|             "columnName": "url", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "timelineUserId", | ||||
|             "columnName": "timelineUserId", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "authorServerId", | ||||
|             "columnName": "authorServerId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "inReplyToId", | ||||
|             "columnName": "inReplyToId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "inReplyToAccountId", | ||||
|             "columnName": "inReplyToAccountId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "content", | ||||
|             "columnName": "content", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "createdAt", | ||||
|             "columnName": "createdAt", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "emojis", | ||||
|             "columnName": "emojis", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "reblogsCount", | ||||
|             "columnName": "reblogsCount", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "favouritesCount", | ||||
|             "columnName": "favouritesCount", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "repliesCount", | ||||
|             "columnName": "repliesCount", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "reblogged", | ||||
|             "columnName": "reblogged", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "bookmarked", | ||||
|             "columnName": "bookmarked", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "favourited", | ||||
|             "columnName": "favourited", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "sensitive", | ||||
|             "columnName": "sensitive", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "spoilerText", | ||||
|             "columnName": "spoilerText", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "visibility", | ||||
|             "columnName": "visibility", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "attachments", | ||||
|             "columnName": "attachments", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "mentions", | ||||
|             "columnName": "mentions", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "tags", | ||||
|             "columnName": "tags", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "application", | ||||
|             "columnName": "application", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "reblogServerId", | ||||
|             "columnName": "reblogServerId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "reblogAccountId", | ||||
|             "columnName": "reblogAccountId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "poll", | ||||
|             "columnName": "poll", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "muted", | ||||
|             "columnName": "muted", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "expanded", | ||||
|             "columnName": "expanded", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "contentCollapsed", | ||||
|             "columnName": "contentCollapsed", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "contentShowing", | ||||
|             "columnName": "contentShowing", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "pinned", | ||||
|             "columnName": "pinned", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "card", | ||||
|             "columnName": "card", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "language", | ||||
|             "columnName": "language", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "columnNames": [ | ||||
|             "serverId", | ||||
|             "timelineUserId" | ||||
|           ], | ||||
|           "autoGenerate": false | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_TimelineStatusEntity_authorServerId_timelineUserId", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "authorServerId", | ||||
|               "timelineUserId" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `index_TimelineStatusEntity_authorServerId_timelineUserId` ON `${TABLE_NAME}` (`authorServerId`, `timelineUserId`)" | ||||
|           } | ||||
|         ], | ||||
|         "foreignKeys": [ | ||||
|           { | ||||
|             "table": "TimelineAccountEntity", | ||||
|             "onDelete": "NO ACTION", | ||||
|             "onUpdate": "NO ACTION", | ||||
|             "columns": [ | ||||
|               "authorServerId", | ||||
|               "timelineUserId" | ||||
|             ], | ||||
|             "referencedColumns": [ | ||||
|               "serverId", | ||||
|               "timelineUserId" | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "TimelineAccountEntity", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `timelineUserId` INTEGER NOT NULL, `localUsername` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `url` TEXT NOT NULL, `avatar` TEXT NOT NULL, `emojis` TEXT NOT NULL, `bot` INTEGER NOT NULL, PRIMARY KEY(`serverId`, `timelineUserId`))", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "serverId", | ||||
|             "columnName": "serverId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "timelineUserId", | ||||
|             "columnName": "timelineUserId", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "localUsername", | ||||
|             "columnName": "localUsername", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "username", | ||||
|             "columnName": "username", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "displayName", | ||||
|             "columnName": "displayName", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "url", | ||||
|             "columnName": "url", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "avatar", | ||||
|             "columnName": "avatar", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "emojis", | ||||
|             "columnName": "emojis", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "bot", | ||||
|             "columnName": "bot", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "columnNames": [ | ||||
|             "serverId", | ||||
|             "timelineUserId" | ||||
|           ], | ||||
|           "autoGenerate": false | ||||
|         }, | ||||
|         "indices": [], | ||||
|         "foreignKeys": [] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "ConversationEntity", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `id` TEXT NOT NULL, `order` INTEGER NOT NULL, `accounts` TEXT NOT NULL, `unread` INTEGER NOT NULL, `s_id` TEXT NOT NULL, `s_url` TEXT, `s_inReplyToId` TEXT, `s_inReplyToAccountId` TEXT, `s_account` TEXT NOT NULL, `s_content` TEXT NOT NULL, `s_createdAt` INTEGER NOT NULL, `s_emojis` TEXT NOT NULL, `s_favouritesCount` INTEGER NOT NULL, `s_repliesCount` INTEGER NOT NULL, `s_favourited` INTEGER NOT NULL, `s_bookmarked` INTEGER NOT NULL, `s_sensitive` INTEGER NOT NULL, `s_spoilerText` TEXT NOT NULL, `s_attachments` TEXT NOT NULL, `s_mentions` TEXT NOT NULL, `s_tags` TEXT, `s_showingHiddenContent` INTEGER NOT NULL, `s_expanded` INTEGER NOT NULL, `s_collapsed` INTEGER NOT NULL, `s_muted` INTEGER NOT NULL, `s_poll` TEXT, `s_language` TEXT, PRIMARY KEY(`id`, `accountId`))", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "accountId", | ||||
|             "columnName": "accountId", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "id", | ||||
|             "columnName": "id", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "order", | ||||
|             "columnName": "order", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "accounts", | ||||
|             "columnName": "accounts", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "unread", | ||||
|             "columnName": "unread", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.id", | ||||
|             "columnName": "s_id", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.url", | ||||
|             "columnName": "s_url", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.inReplyToId", | ||||
|             "columnName": "s_inReplyToId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.inReplyToAccountId", | ||||
|             "columnName": "s_inReplyToAccountId", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.account", | ||||
|             "columnName": "s_account", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.content", | ||||
|             "columnName": "s_content", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.createdAt", | ||||
|             "columnName": "s_createdAt", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.emojis", | ||||
|             "columnName": "s_emojis", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.favouritesCount", | ||||
|             "columnName": "s_favouritesCount", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.repliesCount", | ||||
|             "columnName": "s_repliesCount", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.favourited", | ||||
|             "columnName": "s_favourited", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.bookmarked", | ||||
|             "columnName": "s_bookmarked", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.sensitive", | ||||
|             "columnName": "s_sensitive", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.spoilerText", | ||||
|             "columnName": "s_spoilerText", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.attachments", | ||||
|             "columnName": "s_attachments", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.mentions", | ||||
|             "columnName": "s_mentions", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.tags", | ||||
|             "columnName": "s_tags", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.showingHiddenContent", | ||||
|             "columnName": "s_showingHiddenContent", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.expanded", | ||||
|             "columnName": "s_expanded", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.collapsed", | ||||
|             "columnName": "s_collapsed", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.muted", | ||||
|             "columnName": "s_muted", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.poll", | ||||
|             "columnName": "s_poll", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastStatus.language", | ||||
|             "columnName": "s_language", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "columnNames": [ | ||||
|             "id", | ||||
|             "accountId" | ||||
|           ], | ||||
|           "autoGenerate": false | ||||
|         }, | ||||
|         "indices": [], | ||||
|         "foreignKeys": [] | ||||
|       } | ||||
|     ], | ||||
|     "views": [], | ||||
|     "setupQueries": [ | ||||
|       "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", | ||||
|       "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7b5271980102f35e55438f46777e3d46')" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
|  | @ -42,6 +42,7 @@ import androidx.recyclerview.widget.RecyclerView; | |||
| import com.bumptech.glide.Glide; | ||||
| import com.keylesspalace.tusky.R; | ||||
| import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding; | ||||
| import com.keylesspalace.tusky.databinding.ItemReportNotificationBinding; | ||||
| import com.keylesspalace.tusky.entity.Emoji; | ||||
| import com.keylesspalace.tusky.entity.Notification; | ||||
| import com.keylesspalace.tusky.entity.Status; | ||||
|  | @ -80,7 +81,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { | |||
|     private static final int VIEW_TYPE_FOLLOW = 2; | ||||
|     private static final int VIEW_TYPE_FOLLOW_REQUEST = 3; | ||||
|     private static final int VIEW_TYPE_PLACEHOLDER = 4; | ||||
|     private static final int VIEW_TYPE_UNKNOWN = 5; | ||||
|     private static final int VIEW_TYPE_REPORT = 5; | ||||
|     private static final int VIEW_TYPE_UNKNOWN = 6; | ||||
| 
 | ||||
|     private static final InputFilter[] COLLAPSE_INPUT_FILTER = new InputFilter[]{SmartLengthInputFilter.INSTANCE}; | ||||
|     private static final InputFilter[] NO_INPUT_FILTER = new InputFilter[0]; | ||||
|  | @ -137,6 +139,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter { | |||
|                         .inflate(R.layout.item_status_placeholder, parent, false); | ||||
|                 return new PlaceholderViewHolder(view); | ||||
|             } | ||||
|             case VIEW_TYPE_REPORT: { | ||||
|                 ItemReportNotificationBinding binding = ItemReportNotificationBinding.inflate(inflater, parent, false); | ||||
|                 return new ReportNotificationViewHolder(binding); | ||||
|             } | ||||
|             default: | ||||
|             case VIEW_TYPE_UNKNOWN: { | ||||
|                 View view = new View(parent.getContext()); | ||||
|  | @ -252,6 +258,13 @@ public class NotificationsAdapter extends RecyclerView.Adapter { | |||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|                 case VIEW_TYPE_REPORT: { | ||||
|                     if (payloadForHolder == null) { | ||||
|                         ReportNotificationViewHolder holder = (ReportNotificationViewHolder) viewHolder; | ||||
|                         holder.setupWithReport(concreteNotification.getAccount(), concreteNotification.getReport(), statusDisplayOptions.animateAvatars(), statusDisplayOptions.animateEmojis()); | ||||
|                         holder.setupActionListener(notificationActionListener, concreteNotification.getReport().getTargetAccount().getId(), concreteNotification.getAccount().getId(), concreteNotification.getReport().getId()); | ||||
|                     } | ||||
|                 } | ||||
|                 default: | ||||
|             } | ||||
|         } | ||||
|  | @ -304,6 +317,9 @@ public class NotificationsAdapter extends RecyclerView.Adapter { | |||
|                 case FOLLOW_REQUEST: { | ||||
|                     return VIEW_TYPE_FOLLOW_REQUEST; | ||||
|                 } | ||||
|                 case REPORT: { | ||||
|                     return VIEW_TYPE_REPORT; | ||||
|                 } | ||||
|                 default: { | ||||
|                     return VIEW_TYPE_UNKNOWN; | ||||
|                 } | ||||
|  | @ -322,6 +338,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter { | |||
| 
 | ||||
|         void onViewStatusForNotificationId(String notificationId); | ||||
| 
 | ||||
|         void onViewReport(String reportId); | ||||
| 
 | ||||
|         void onExpandedChange(boolean expanded, int position); | ||||
| 
 | ||||
|         /** | ||||
|  |  | |||
|  | @ -0,0 +1,90 @@ | |||
| /* Copyright 2021 Tusky Contributors | ||||
|  * | ||||
|  * This file is a part of Tusky. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it under the terms of the | ||||
|  * GNU General Public License as published by the Free Software Foundation; either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even | ||||
|  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||||
|  * Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with Tusky; if not, | ||||
|  * see <http://www.gnu.org/licenses>. */ | ||||
| 
 | ||||
| package com.keylesspalace.tusky.adapter | ||||
| 
 | ||||
| import android.content.Context | ||||
| import androidx.core.content.ContextCompat | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import at.connyduck.sparkbutton.helpers.Utils | ||||
| import com.keylesspalace.tusky.R | ||||
| import com.keylesspalace.tusky.adapter.NotificationsAdapter.NotificationActionListener | ||||
| import com.keylesspalace.tusky.databinding.ItemReportNotificationBinding | ||||
| import com.keylesspalace.tusky.entity.Report | ||||
| import com.keylesspalace.tusky.entity.TimelineAccount | ||||
| import com.keylesspalace.tusky.util.TimestampUtils | ||||
| import com.keylesspalace.tusky.util.emojify | ||||
| import com.keylesspalace.tusky.util.loadAvatar | ||||
| import com.keylesspalace.tusky.util.unicodeWrap | ||||
| import java.util.Date | ||||
| 
 | ||||
| class ReportNotificationViewHolder( | ||||
|     private val binding: ItemReportNotificationBinding, | ||||
| ) : RecyclerView.ViewHolder(binding.root) { | ||||
| 
 | ||||
|     fun setupWithReport(reporter: TimelineAccount, report: Report, animateAvatar: Boolean, animateEmojis: Boolean) { | ||||
|         val reporterName = reporter.name.unicodeWrap().emojify(reporter.emojis, itemView, animateEmojis) | ||||
|         val reporteeName = report.targetAccount.name.unicodeWrap().emojify(report.targetAccount.emojis, itemView, animateEmojis) | ||||
|         val icon = ContextCompat.getDrawable(itemView.context, R.drawable.ic_flag_24dp) | ||||
| 
 | ||||
|         binding.notificationTopText.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null) | ||||
|         binding.notificationTopText.text = itemView.context.getString(R.string.notification_header_report_format, reporterName, reporteeName) | ||||
|         binding.notificationSummary.text = itemView.context.getString(R.string.notification_summary_report_format, TimestampUtils.getRelativeTimeSpanString(itemView.context, report.createdAt.time, Date().time), report.status_ids?.size ?: 0) | ||||
|         binding.notificationCategory.text = getTranslatedCategory(itemView.context, report.category) | ||||
| 
 | ||||
|         // Fancy avatar inset | ||||
|         val padding = Utils.dpToPx(binding.notificationReporteeAvatar.context, 12) | ||||
|         binding.notificationReporteeAvatar.setPaddingRelative(0, 0, padding, padding) | ||||
| 
 | ||||
|         loadAvatar( | ||||
|             report.targetAccount.avatar, | ||||
|             binding.notificationReporteeAvatar, | ||||
|             itemView.context.resources.getDimensionPixelSize(R.dimen.avatar_radius_36dp), | ||||
|             animateAvatar, | ||||
|         ) | ||||
|         loadAvatar( | ||||
|             reporter.avatar, | ||||
|             binding.notificationReporterAvatar, | ||||
|             itemView.context.resources.getDimensionPixelSize(R.dimen.avatar_radius_24dp), | ||||
|             animateAvatar, | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fun setupActionListener(listener: NotificationActionListener, reporteeId: String, reporterId: String, reportId: String) { | ||||
|         binding.notificationReporteeAvatar.setOnClickListener { | ||||
|             val position = bindingAdapterPosition | ||||
|             if (position != RecyclerView.NO_POSITION) { | ||||
|                 listener.onViewAccount(reporteeId) | ||||
|             } | ||||
|         } | ||||
|         binding.notificationReporterAvatar.setOnClickListener { | ||||
|             val position = bindingAdapterPosition | ||||
|             if (position != RecyclerView.NO_POSITION) { | ||||
|                 listener.onViewAccount(reporterId) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         itemView.setOnClickListener { listener.onViewReport(reportId) } | ||||
|     } | ||||
| 
 | ||||
|     private fun getTranslatedCategory(context: Context, rawCategory: String): String { | ||||
|         return when (rawCategory) { | ||||
|             "violation" -> context.getString(R.string.report_category_violation) | ||||
|             "spam" -> context.getString(R.string.report_category_spam) | ||||
|             "other" -> context.getString(R.string.report_category_other) | ||||
|             else -> rawCategory | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -120,6 +120,7 @@ public class NotificationHelper { | |||
|     public static final String CHANNEL_SUBSCRIPTIONS = "CHANNEL_SUBSCRIPTIONS"; | ||||
|     public static final String CHANNEL_SIGN_UP = "CHANNEL_SIGN_UP"; | ||||
|     public static final String CHANNEL_UPDATES = "CHANNEL_UPDATES"; | ||||
|     public static final String CHANNEL_REPORT = "CHANNEL_REPORT"; | ||||
| 
 | ||||
|     /** | ||||
|      * WorkManager Tag | ||||
|  | @ -401,6 +402,7 @@ public class NotificationHelper { | |||
|                     CHANNEL_SUBSCRIPTIONS + account.getIdentifier(), | ||||
|                     CHANNEL_SIGN_UP + account.getIdentifier(), | ||||
|                     CHANNEL_UPDATES + account.getIdentifier(), | ||||
|                     CHANNEL_REPORT + account.getIdentifier(), | ||||
|             }; | ||||
|             int[] channelNames = { | ||||
|                     R.string.notification_mention_name, | ||||
|  | @ -412,6 +414,7 @@ public class NotificationHelper { | |||
|                     R.string.notification_subscription_name, | ||||
|                     R.string.notification_sign_up_name, | ||||
|                     R.string.notification_update_name, | ||||
|                     R.string.notification_report_name, | ||||
|             }; | ||||
|             int[] channelDescriptions = { | ||||
|                     R.string.notification_mention_descriptions, | ||||
|  | @ -423,6 +426,7 @@ public class NotificationHelper { | |||
|                     R.string.notification_subscription_description, | ||||
|                     R.string.notification_sign_up_description, | ||||
|                     R.string.notification_update_description, | ||||
|                     R.string.notification_report_description, | ||||
|             }; | ||||
| 
 | ||||
|             List<NotificationChannel> channels = new ArrayList<>(6); | ||||
|  | @ -564,6 +568,8 @@ public class NotificationHelper { | |||
|                 return account.getNotificationsSignUps(); | ||||
|             case UPDATE: | ||||
|                 return account.getNotificationsUpdates(); | ||||
|             case REPORT: | ||||
|                 return account.getNotificationsReports(); | ||||
|             default: | ||||
|                 return false; | ||||
|         } | ||||
|  | @ -593,6 +599,10 @@ public class NotificationHelper { | |||
|                 return CHANNEL_POLL + account.getIdentifier(); | ||||
|             case SIGN_UP: | ||||
|                 return CHANNEL_SIGN_UP + account.getIdentifier(); | ||||
|             case UPDATE: | ||||
|                 return CHANNEL_UPDATES + account.getIdentifier(); | ||||
|             case REPORT: | ||||
|                 return CHANNEL_REPORT + account.getIdentifier(); | ||||
|             default: | ||||
|                 return null; | ||||
|         } | ||||
|  | @ -678,6 +688,8 @@ public class NotificationHelper { | |||
|                 return String.format(context.getString(R.string.notification_sign_up_format), accountName); | ||||
|             case UPDATE: | ||||
|                 return String.format(context.getString(R.string.notification_update_format), accountName); | ||||
|             case REPORT: | ||||
|                 return context.getString(R.string.notification_report_format, account.getDomain()); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | @ -715,6 +727,12 @@ public class NotificationHelper { | |||
|                     } | ||||
|                     return builder.toString(); | ||||
|                 } | ||||
|             case REPORT: | ||||
|                 return context.getString( | ||||
|                         R.string.notification_header_report_format, | ||||
|                         StringUtils.unicodeWrap(notification.getAccount().getName()), | ||||
|                         StringUtils.unicodeWrap(notification.getReport().getTargetAccount().getName()) | ||||
|                 ); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  |  | |||
|  | @ -144,6 +144,17 @@ class NotificationPreferencesFragment : PreferenceFragmentCompat(), Injectable { | |||
|                         true | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 switchPreference { | ||||
|                     setTitle(R.string.pref_title_notification_filter_reports) | ||||
|                     key = PrefKeys.NOTIFICATION_FILTER_REPORTS | ||||
|                     isIconSpaceReserved = false | ||||
|                     isChecked = activeAccount.notificationsReports | ||||
|                     setOnPreferenceChangeListener { _, newValue -> | ||||
|                         updateAccount { it.notificationsReports = newValue as Boolean } | ||||
|                         true | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             preferenceCategory(R.string.pref_title_notification_alerts) { category -> | ||||
|  |  | |||
|  | @ -54,6 +54,7 @@ data class AccountEntity( | |||
|     var notificationsSubscriptions: Boolean = true, | ||||
|     var notificationsSignUps: Boolean = true, | ||||
|     var notificationsUpdates: Boolean = true, | ||||
|     var notificationsReports: Boolean = true, | ||||
|     var notificationSound: Boolean = true, | ||||
|     var notificationVibration: Boolean = true, | ||||
|     var notificationLight: Boolean = true, | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ import java.io.File; | |||
|  */ | ||||
| @Database(entities = { DraftEntity.class, AccountEntity.class, InstanceEntity.class, TimelineStatusEntity.class, | ||||
|                 TimelineAccountEntity.class,  ConversationEntity.class | ||||
|         }, version = 43) | ||||
|         }, version = 44) | ||||
| public abstract class AppDatabase extends RoomDatabase { | ||||
| 
 | ||||
|     public abstract AccountDao accountDao(); | ||||
|  | @ -617,4 +617,11 @@ public abstract class AppDatabase extends RoomDatabase { | |||
|             database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `defaultPostLanguage` TEXT NOT NULL DEFAULT ''"); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     public static final Migration MIGRATION_43_44 = new Migration(43, 44) { | ||||
|         @Override | ||||
|         public void migrate(@NonNull SupportSQLiteDatabase database) { | ||||
|             database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `notificationsReports` INTEGER NOT NULL DEFAULT 1"); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ class AppModule { | |||
|                 AppDatabase.MIGRATION_32_33, AppDatabase.MIGRATION_33_34, AppDatabase.MIGRATION_34_35, | ||||
|                 AppDatabase.MIGRATION_35_36, AppDatabase.MIGRATION_36_37, AppDatabase.MIGRATION_37_38, | ||||
|                 AppDatabase.MIGRATION_38_39, AppDatabase.MIGRATION_39_40, AppDatabase.MIGRATION_40_41, | ||||
|                 AppDatabase.MIGRATION_41_42, AppDatabase.MIGRATION_42_43, | ||||
|                 AppDatabase.MIGRATION_41_42, AppDatabase.MIGRATION_42_43, AppDatabase.MIGRATION_43_44, | ||||
|             ) | ||||
|             .build() | ||||
|     } | ||||
|  |  | |||
|  | @ -25,7 +25,8 @@ data class Notification( | |||
|     val type: Type, | ||||
|     val id: String, | ||||
|     val account: TimelineAccount, | ||||
|     val status: Status? | ||||
|     val status: Status?, | ||||
|     val report: Report?, | ||||
| ) { | ||||
| 
 | ||||
|     @JsonAdapter(NotificationTypeAdapter::class) | ||||
|  | @ -40,6 +41,7 @@ data class Notification( | |||
|         STATUS("status"), | ||||
|         SIGN_UP("admin.sign_up"), | ||||
|         UPDATE("update"), | ||||
|         REPORT("admin.report"), | ||||
|         ; | ||||
| 
 | ||||
|         companion object { | ||||
|  | @ -52,7 +54,7 @@ data class Notification( | |||
|                 } | ||||
|                 return UNKNOWN | ||||
|             } | ||||
|             val asList = listOf(MENTION, REBLOG, FAVOURITE, FOLLOW, FOLLOW_REQUEST, POLL, STATUS, SIGN_UP, UPDATE) | ||||
|             val asList = listOf(MENTION, REBLOG, FAVOURITE, FOLLOW, FOLLOW_REQUEST, POLL, STATUS, SIGN_UP, UPDATE, REPORT) | ||||
|         } | ||||
| 
 | ||||
|         override fun toString(): String { | ||||
|  |  | |||
							
								
								
									
										12
									
								
								app/src/main/java/com/keylesspalace/tusky/entity/Report.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/src/main/java/com/keylesspalace/tusky/entity/Report.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| package com.keylesspalace.tusky.entity | ||||
| 
 | ||||
| import com.google.gson.annotations.SerializedName | ||||
| import java.util.Date | ||||
| 
 | ||||
| data class Report( | ||||
|     val id: String, | ||||
|     val category: String, | ||||
|     val status_ids: List<String>?, | ||||
|     @SerializedName("created_at") val createdAt: Date, | ||||
|     @SerializedName("target_account") val targetAccount: TimelineAccount, | ||||
| ) | ||||
|  | @ -80,6 +80,7 @@ import com.keylesspalace.tusky.settings.PrefKeys; | |||
| import com.keylesspalace.tusky.util.CardViewMode; | ||||
| import com.keylesspalace.tusky.util.Either; | ||||
| import com.keylesspalace.tusky.util.HttpHeaderLink; | ||||
| import com.keylesspalace.tusky.util.LinkHelper; | ||||
| import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate; | ||||
| import com.keylesspalace.tusky.util.ListUtils; | ||||
| import com.keylesspalace.tusky.util.NotificationTypeConverterKt; | ||||
|  | @ -711,6 +712,8 @@ public class NotificationsFragment extends SFragment implements | |||
|                 return getString(R.string.notification_sign_up_name); | ||||
|             case UPDATE: | ||||
|                 return getString(R.string.notification_update_name); | ||||
|             case REPORT: | ||||
|                 return getString(R.string.notification_report_name); | ||||
|             default: | ||||
|                 return "Unknown"; | ||||
|         } | ||||
|  | @ -800,6 +803,11 @@ public class NotificationsFragment extends SFragment implements | |||
|         Log.w(TAG, "Didn't find a notification for ID: " + notificationId); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onViewReport(String reportId) { | ||||
|         LinkHelper.openLink(getContext(), String.format("https://%s/admin/reports/%s", accountManager.getActiveAccount().getDomain(), reportId)); | ||||
|     } | ||||
| 
 | ||||
|     private void onPreferenceChanged(String key) { | ||||
|         switch (key) { | ||||
|             case "fabHide": { | ||||
|  |  | |||
|  | @ -62,6 +62,7 @@ object PrefKeys { | |||
|     const val NOTIFICATION_FILTER_SUBSCRIPTIONS = "notificationFilterSubscriptions" | ||||
|     const val NOTIFICATION_FILTER_SIGN_UPS = "notificationFilterSignUps" | ||||
|     const val NOTIFICATION_FILTER_UPDATES = "notificationFilterUpdates" | ||||
|     const val NOTIFICATION_FILTER_REPORTS = "notificationFilterReports" | ||||
| 
 | ||||
|     const val TAB_FILTER_HOME_REPLIES = "tabFilterHomeReplies_v2" // This was changed once to reset an unintentionally set default. | ||||
|     const val TAB_FILTER_HOME_BOOSTS = "tabFilterHomeBoosts" | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ fun Notification.toViewData( | |||
|         this.type, | ||||
|         this.id, | ||||
|         this.account, | ||||
|         this.status?.toViewData(isShowingContent, isExpanded, isCollapsed) | ||||
|         this.status?.toViewData(isShowingContent, isExpanded, isCollapsed), | ||||
|         this.report, | ||||
|     ) | ||||
| } | ||||
|  |  | |||
|  | @ -17,8 +17,8 @@ package com.keylesspalace.tusky.viewdata; | |||
| 
 | ||||
| import androidx.annotation.Nullable; | ||||
| 
 | ||||
| import com.keylesspalace.tusky.entity.Account; | ||||
| import com.keylesspalace.tusky.entity.Notification; | ||||
| import com.keylesspalace.tusky.entity.Report; | ||||
| import com.keylesspalace.tusky.entity.TimelineAccount; | ||||
| 
 | ||||
| import java.util.Objects; | ||||
|  | @ -48,13 +48,16 @@ public abstract class NotificationViewData { | |||
|         private final TimelineAccount account; | ||||
|         @Nullable | ||||
|         private final StatusViewData.Concrete statusViewData; | ||||
|         @Nullable | ||||
|         private final Report report; | ||||
| 
 | ||||
|         public Concrete(Notification.Type type, String id, TimelineAccount account, | ||||
|                         @Nullable StatusViewData.Concrete statusViewData) { | ||||
|                         @Nullable StatusViewData.Concrete statusViewData, @Nullable Report report) { | ||||
|             this.type = type; | ||||
|             this.id = id; | ||||
|             this.account = account; | ||||
|             this.statusViewData = statusViewData; | ||||
|             this.report = report; | ||||
|         } | ||||
| 
 | ||||
|         public Notification.Type getType() { | ||||
|  | @ -74,6 +77,11 @@ public abstract class NotificationViewData { | |||
|             return statusViewData; | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         public Report getReport() { | ||||
|             return report; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public long getViewDataId() { | ||||
|             return id.hashCode(); | ||||
|  | @ -87,7 +95,8 @@ public abstract class NotificationViewData { | |||
|             return type == concrete.type && | ||||
|                     Objects.equals(id, concrete.id) && | ||||
|                     account.getId().equals(concrete.account.getId()) && | ||||
|                     (Objects.equals(statusViewData, concrete.statusViewData)); | ||||
|                     (Objects.equals(statusViewData, concrete.statusViewData)) && | ||||
|                     (Objects.equals(report, concrete.report)); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|  | @ -97,7 +106,7 @@ public abstract class NotificationViewData { | |||
|         } | ||||
| 
 | ||||
|         public Concrete copyWithStatus(@Nullable StatusViewData.Concrete statusViewData) { | ||||
|             return new Concrete(type, id, account, statusViewData); | ||||
|             return new Concrete(type, id, account, statusViewData, report); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								app/src/main/res/drawable/ic_flag_24dp.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/src/main/res/drawable/ic_flag_24dp.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24" | ||||
|     android:tint="@color/tusky_blue"> | ||||
|   <path | ||||
|       android:fillColor="@android:color/white" | ||||
|       android:pathData="M14.4,6L14,4H5v17h2v-7h5.6l0.4,2h7V6z"/> | ||||
| </vector> | ||||
							
								
								
									
										81
									
								
								app/src/main/res/layout/item_report_notification.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								app/src/main/res/layout/item_report_notification.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:id="@+id/notification_report" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:orientation="vertical" | ||||
|     android:paddingLeft="14dp" | ||||
|     android:paddingRight="14dp"> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/notification_top_text" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:layout_constraintLeft_toLeftOf="parent" | ||||
|         android:layout_marginTop="8dp" | ||||
|         android:drawablePadding="10dp" | ||||
|         android:ellipsize="end" | ||||
|         android:gravity="center_vertical" | ||||
|         android:maxLines="1" | ||||
|         android:paddingStart="28dp" | ||||
|         android:textColor="?android:textColorSecondary" | ||||
|         android:textSize="?attr/status_text_medium" | ||||
|         tools:text="Someone reported someone else" /> | ||||
| 
 | ||||
|     <ImageView | ||||
|         android:id="@+id/notification_reportee_avatar" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="48dp" | ||||
|         app:layout_constraintTop_toBottomOf="@id/notification_top_text" | ||||
|         app:layout_constraintLeft_toLeftOf="parent" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:layout_marginEnd="14dp" | ||||
|         android:layout_marginBottom="14dp" | ||||
|         android:contentDescription="@string/action_view_profile" | ||||
|         android:scaleType="centerCrop" | ||||
|         tools:ignore="RtlHardcoded,RtlSymmetry" | ||||
|         tools:src="@drawable/avatar_default" /> | ||||
| 
 | ||||
|     <ImageView | ||||
|         android:id="@+id/notification_reporter_avatar" | ||||
|         android:layout_width="24dp" | ||||
|         android:layout_height="24dp" | ||||
|         app:layout_constraintRight_toRightOf="@id/notification_reportee_avatar" | ||||
|         app:layout_constraintBottom_toBottomOf="@id/notification_reportee_avatar" | ||||
|         /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/notification_summary" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="-4dp" | ||||
|         android:layout_marginStart="14dp" | ||||
|         app:layout_constraintTop_toTopOf="@id/notification_reportee_avatar" | ||||
|         app:layout_constraintLeft_toRightOf="@id/notification_reporter_avatar" | ||||
|         android:importantForAccessibility="no" | ||||
|         android:hyphenationFrequency="full" | ||||
|         android:lineSpacingMultiplier="1.1" | ||||
|         android:textColor="?android:textColorTertiary" | ||||
|         android:textSize="?attr/status_text_medium" | ||||
|         tools:text="30 minutes ago - 2 posts" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/notification_category" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="14dp" | ||||
|         app:layout_constraintTop_toBottomOf="@id/notification_summary" | ||||
|         app:layout_constraintLeft_toRightOf="@id/notification_reporter_avatar" | ||||
|         android:importantForAccessibility="no" | ||||
|         android:hyphenationFrequency="full" | ||||
|         android:lineSpacingMultiplier="1.1" | ||||
|         android:paddingBottom="10dp" | ||||
|         android:textColor="?android:textColorTertiary" | ||||
|         android:textSize="?attr/status_text_medium" | ||||
|         android:textStyle="bold" | ||||
|         tools:text="Spam" /> | ||||
| 
 | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
|  | @ -73,6 +73,9 @@ | |||
|     <string name="notification_sign_up_format">%s signed up</string> | ||||
|     <string name="notification_subscription_format">%s just posted</string> | ||||
|     <string name="notification_update_format">%s edited their post</string> | ||||
|     <string name="notification_report_format">New report on %s</string> | ||||
|     <string name="notification_header_report_format">%s reported %s</string> | ||||
|     <string name="notification_summary_report_format">%s · %d posts attached</string> | ||||
| 
 | ||||
|     <string name="report_username_format">Report @%s</string> | ||||
|     <string name="report_comment_hint">Additional comments?</string> | ||||
|  | @ -244,6 +247,7 @@ | |||
|     <string name="pref_title_notification_filter_subscriptions">somebody I\'m subscribed to published a new post</string> | ||||
|     <string name="pref_title_notification_filter_sign_ups">somebody signed up</string> | ||||
|     <string name="pref_title_notification_filter_updates">a post I\'ve interacted with is edited</string> | ||||
|     <string name="pref_title_notification_filter_reports">there\'s a new report</string> | ||||
|     <string name="pref_title_appearance_settings">Appearance</string> | ||||
|     <string name="pref_title_app_theme">App Theme</string> | ||||
|     <string name="pref_title_timelines">Timelines</string> | ||||
|  | @ -319,6 +323,8 @@ | |||
|     <string name="notification_sign_up_description">Notifications about new users</string> | ||||
|     <string name="notification_update_name">Post edits</string> | ||||
|     <string name="notification_update_description">Notifications when posts you\'ve interacted with are edited</string> | ||||
|     <string name="notification_report_name">Reports</string> | ||||
|     <string name="notification_report_description">Notifications about moderation reports</string> | ||||
| 
 | ||||
|     <string name="notification_mention_format">%s mentioned you</string> | ||||
|     <string name="notification_summary_large">%1$s, %2$s, %3$s and %4$d others</string> | ||||
|  | @ -684,6 +690,11 @@ | |||
| 
 | ||||
|     <string name="instance_rule_info">By logging in you agree to the rules of %s.</string> | ||||
|     <string name="instance_rule_title">%s rules</string> | ||||
| 
 | ||||
|     <string name="report_category_violation">Rule violation</string> | ||||
|     <string name="report_category_spam">Spam</string> | ||||
|     <string name="report_category_other">Other</string> | ||||
| 
 | ||||
|     <string name="action_unfollow_hashtag_format">Unfollow #%s?</string> | ||||
| 
 | ||||
| </resources> | ||||
|  |  | |||
|  | @ -102,7 +102,8 @@ class MainActivityTest { | |||
|                         url = "https://mastodon.example/@ConnyDuck", | ||||
|                         avatar = "https://mastodon.example/system/accounts/avatars/000/150/486/original/ab27d7ddd18a10ea.jpg" | ||||
|                     ), | ||||
|                     status = null | ||||
|                     status = null, | ||||
|                     report = null, | ||||
|                 ), | ||||
|                 accountEntity, | ||||
|                 true | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue