mirror of
https://github.com/accelforce/Yuito
synced 2025-02-01 16:36:50 +01:00
Merge remote-tracking branch 'tuskyapp/develop'
This commit is contained in:
commit
1370eedc10
@ -103,11 +103,11 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||
}
|
||||
|
||||
ext.lifecycleVersion = "2.2.0"
|
||||
ext.roomVersion = '2.2.4'
|
||||
ext.retrofitVersion = '2.7.1'
|
||||
ext.okhttpVersion = '4.3.1'
|
||||
ext.glideVersion = '4.10.0'
|
||||
ext.daggerVersion = '2.26'
|
||||
ext.roomVersion = '2.2.5'
|
||||
ext.retrofitVersion = '2.8.1'
|
||||
ext.okhttpVersion = '4.4.0'
|
||||
ext.glideVersion = '4.11.0'
|
||||
ext.daggerVersion = '2.27'
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
@ -120,12 +120,12 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0-alpha02"
|
||||
implementation "androidx.fragment:fragment-ktx:1.2.2"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0-beta01"
|
||||
implementation "androidx.fragment:fragment-ktx:1.2.4"
|
||||
implementation "androidx.browser:browser:1.2.0"
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
implementation "androidx.exifinterface:exifinterface:1.1.0"
|
||||
implementation "androidx.exifinterface:exifinterface:1.2.0"
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation "androidx.preference:preference:1.1.0"
|
||||
implementation "androidx.sharetarget:sharetarget:1.0.0-rc01"
|
||||
@ -135,7 +135,7 @@ dependencies {
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycleVersion"
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
implementation "androidx.paging:paging-runtime-ktx:2.1.1"
|
||||
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
||||
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
||||
implementation "androidx.room:room-runtime:$roomVersion"
|
||||
implementation "androidx.room:room-rxjava2:$roomVersion"
|
||||
@ -150,7 +150,7 @@ dependencies {
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"
|
||||
|
||||
implementation "org.conscrypt:conscrypt-android:2.2.1"
|
||||
implementation "org.conscrypt:conscrypt-android:2.4.0"
|
||||
|
||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:$glideVersion"
|
||||
@ -168,7 +168,7 @@ dependencies {
|
||||
implementation "com.google.dagger:dagger-android-support:$daggerVersion"
|
||||
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
|
||||
|
||||
implementation "com.github.connyduck:sparkbutton:3.0.0"
|
||||
implementation "com.github.connyduck:sparkbutton:4.0.0"
|
||||
|
||||
implementation "com.github.chrisbanes:PhotoView:2.3.0"
|
||||
|
||||
|
735
app/schemas/com.keylesspalace.tusky.db.AppDatabase/22.json
Normal file
735
app/schemas/com.keylesspalace.tusky.db.AppDatabase/22.json
Normal file
@ -0,0 +1,735 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 22,
|
||||
"identityHash": "eaa3c4d012fe743948343983fe1ae493",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "TootEntity",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `text` TEXT, `urls` TEXT, `descriptions` TEXT, `contentWarning` TEXT, `inReplyToId` TEXT, `inReplyToText` TEXT, `inReplyToUsername` TEXT, `visibility` INTEGER, `poll` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"columnName": "uid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "urls",
|
||||
"columnName": "urls",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "descriptions",
|
||||
"columnName": "descriptions",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "contentWarning",
|
||||
"columnName": "contentWarning",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "inReplyToId",
|
||||
"columnName": "inReplyToId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "inReplyToText",
|
||||
"columnName": "inReplyToText",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "inReplyToUsername",
|
||||
"columnName": "inReplyToUsername",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "poll",
|
||||
"columnName": "poll",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"uid"
|
||||
],
|
||||
"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, `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, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER 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)",
|
||||
"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": "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": "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": "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
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_AccountEntity_domain_accountId",
|
||||
"unique": true,
|
||||
"columnNames": [
|
||||
"domain",
|
||||
"accountId"
|
||||
],
|
||||
"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, `version` TEXT, 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": "version",
|
||||
"columnName": "version",
|
||||
"affinity": "TEXT",
|
||||
"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, `reblogged` INTEGER NOT NULL, `bookmarked` INTEGER NOT NULL, `favourited` INTEGER NOT NULL, `sensitive` INTEGER NOT NULL, `spoilerText` TEXT, `visibility` INTEGER, `attachments` TEXT, `mentions` TEXT, `application` TEXT, `reblogServerId` TEXT, `reblogAccountId` TEXT, `poll` 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": "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": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachments",
|
||||
"columnName": "attachments",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "mentions",
|
||||
"columnName": "mentions",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"serverId",
|
||||
"timelineUserId"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_TimelineStatusEntity_authorServerId_timelineUserId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"authorServerId",
|
||||
"timelineUserId"
|
||||
],
|
||||
"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, `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_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_showingHiddenContent` INTEGER NOT NULL, `s_expanded` INTEGER NOT NULL, `s_collapsible` INTEGER NOT NULL, `s_collapsed` INTEGER NOT NULL, `s_poll` TEXT, PRIMARY KEY(`id`, `accountId`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "accountId",
|
||||
"columnName": "accountId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"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.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.showingHiddenContent",
|
||||
"columnName": "s_showingHiddenContent",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.expanded",
|
||||
"columnName": "s_expanded",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.collapsible",
|
||||
"columnName": "s_collapsible",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.collapsed",
|
||||
"columnName": "s_collapsed",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.poll",
|
||||
"columnName": "s_poll",
|
||||
"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, 'eaa3c4d012fe743948343983fe1ae493')"
|
||||
]
|
||||
}
|
||||
}
|
741
app/schemas/com.keylesspalace.tusky.db.AppDatabase/23.json
Normal file
741
app/schemas/com.keylesspalace.tusky.db.AppDatabase/23.json
Normal file
@ -0,0 +1,741 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 23,
|
||||
"identityHash": "03a7436643ef356198742c5f8e054f5f",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "TootEntity",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `text` TEXT, `urls` TEXT, `descriptions` TEXT, `contentWarning` TEXT, `inReplyToId` TEXT, `inReplyToText` TEXT, `inReplyToUsername` TEXT, `visibility` INTEGER, `poll` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uid",
|
||||
"columnName": "uid",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "urls",
|
||||
"columnName": "urls",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "descriptions",
|
||||
"columnName": "descriptions",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "contentWarning",
|
||||
"columnName": "contentWarning",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "inReplyToId",
|
||||
"columnName": "inReplyToId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "inReplyToText",
|
||||
"columnName": "inReplyToText",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "inReplyToUsername",
|
||||
"columnName": "inReplyToUsername",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "poll",
|
||||
"columnName": "poll",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"uid"
|
||||
],
|
||||
"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, `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, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER 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)",
|
||||
"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": "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": "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": "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
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_AccountEntity_domain_accountId",
|
||||
"unique": true,
|
||||
"columnNames": [
|
||||
"domain",
|
||||
"accountId"
|
||||
],
|
||||
"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, `version` TEXT, 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": "version",
|
||||
"columnName": "version",
|
||||
"affinity": "TEXT",
|
||||
"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, `reblogged` INTEGER NOT NULL, `bookmarked` INTEGER NOT NULL, `favourited` INTEGER NOT NULL, `sensitive` INTEGER NOT NULL, `spoilerText` TEXT, `visibility` INTEGER, `attachments` TEXT, `mentions` TEXT, `application` TEXT, `reblogServerId` TEXT, `reblogAccountId` TEXT, `poll` TEXT, `muted` INTEGER, 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": "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": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachments",
|
||||
"columnName": "attachments",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "mentions",
|
||||
"columnName": "mentions",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"serverId",
|
||||
"timelineUserId"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_TimelineStatusEntity_authorServerId_timelineUserId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"authorServerId",
|
||||
"timelineUserId"
|
||||
],
|
||||
"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, `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_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_showingHiddenContent` INTEGER NOT NULL, `s_expanded` INTEGER NOT NULL, `s_collapsible` INTEGER NOT NULL, `s_collapsed` INTEGER NOT NULL, `s_poll` TEXT, PRIMARY KEY(`id`, `accountId`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "accountId",
|
||||
"columnName": "accountId",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"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.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.showingHiddenContent",
|
||||
"columnName": "s_showingHiddenContent",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.expanded",
|
||||
"columnName": "s_expanded",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.collapsible",
|
||||
"columnName": "s_collapsible",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.collapsed",
|
||||
"columnName": "s_collapsed",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastStatus.poll",
|
||||
"columnName": "s_poll",
|
||||
"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, '03a7436643ef356198742c5f8e054f5f')"
|
||||
]
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.1 KiB |
@ -52,8 +52,6 @@ import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||
import com.keylesspalace.tusky.components.report.ReportActivity
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.entity.Field
|
||||
import com.keylesspalace.tusky.entity.IdentityProof
|
||||
import com.keylesspalace.tusky.entity.Relationship
|
||||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity
|
||||
import com.keylesspalace.tusky.interfaces.LinkListener
|
||||
@ -311,7 +309,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
||||
* Subscribe to data loaded at the view model
|
||||
*/
|
||||
private fun subscribeObservables() {
|
||||
viewModel.accountData.observe(this, Observer<Resource<Account>> {
|
||||
viewModel.accountData.observe(this, Observer {
|
||||
when (it) {
|
||||
is Success -> onAccountChanged(it.data)
|
||||
is Error -> {
|
||||
@ -321,7 +319,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
||||
}
|
||||
}
|
||||
})
|
||||
viewModel.relationshipData.observe(this, Observer<Resource<Relationship>> {
|
||||
viewModel.relationshipData.observe(this, Observer {
|
||||
val relation = it?.data
|
||||
if (relation != null) {
|
||||
onRelationshipChanged(relation)
|
||||
@ -334,7 +332,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
||||
}
|
||||
|
||||
})
|
||||
viewModel.accountFieldData.observe(this, Observer<List<Either<IdentityProof, Field>>> {
|
||||
viewModel.accountFieldData.observe(this, Observer {
|
||||
accountFieldAdapter.fields = it
|
||||
accountFieldAdapter.notifyDataSetChanged()
|
||||
|
||||
@ -681,6 +679,30 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun toggleBlock() {
|
||||
if (viewModel.relationshipData.value?.data?.blocking != true) {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage(getString(R.string.dialog_block_warning, loadedAccount?.username))
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> viewModel.changeBlockState() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
} else {
|
||||
viewModel.changeBlockState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleMute() {
|
||||
if (viewModel.relationshipData.value?.data?.muting != true) {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage(getString(R.string.dialog_mute_warning, loadedAccount?.username))
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> viewModel.changeMuteState() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
} else {
|
||||
viewModel.changeMuteState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun mention() {
|
||||
loadedAccount?.let {
|
||||
val intent = ComposeActivity.startIntent(this,
|
||||
@ -727,11 +749,11 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
|
||||
return true
|
||||
}
|
||||
R.id.action_block -> {
|
||||
viewModel.changeBlockState()
|
||||
toggleBlock()
|
||||
return true
|
||||
}
|
||||
R.id.action_mute -> {
|
||||
viewModel.changeMuteState()
|
||||
toggleMute()
|
||||
return true
|
||||
}
|
||||
R.id.action_mute_domain -> {
|
||||
|
@ -77,7 +77,7 @@ class AccountsInListFragment : DialogFragment(), Injectable {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStyle(STYLE_NORMAL, R.style.TuskyDialogFragmentStyle)
|
||||
viewModel = viewModelFactory.create(AccountsInListViewModel::class.java)
|
||||
val args = arguments!!
|
||||
val args = requireArguments()
|
||||
listId = args.getString(LIST_ID_ARG)!!
|
||||
listName = args.getString(LIST_NAME_ARG)!!
|
||||
|
||||
@ -255,12 +255,12 @@ class AccountsInListFragment : DialogFragment(), Injectable {
|
||||
loadAvatar(account.avatar, avatar, radius, animateAvatar)
|
||||
|
||||
rejectButton.apply {
|
||||
if (inAList) {
|
||||
contentDescription = if (inAList) {
|
||||
setImageResource(R.drawable.ic_reject_24dp)
|
||||
contentDescription = getString(R.string.action_remove_from_list)
|
||||
getString(R.string.action_remove_from_list)
|
||||
} else {
|
||||
setImageResource(R.drawable.ic_plus_24dp)
|
||||
contentDescription = getString(R.string.action_add_to_list)
|
||||
getString(R.string.action_add_to_list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
|
||||
|
||||
val positiveButton = dialog.getButton(Dialog.BUTTON_POSITIVE)
|
||||
editText.onTextChanged { s, _, _, _ ->
|
||||
positiveButton.isEnabled = !s.isNullOrBlank()
|
||||
positiveButton.isEnabled = !s.isBlank()
|
||||
}
|
||||
editText.setText(list?.title)
|
||||
editText.text?.let { editText.setSelection(it.length) }
|
||||
|
@ -129,7 +129,7 @@ class PreferencesActivity : BaseActivity(), SharedPreferences.OnSharedPreference
|
||||
|
||||
}
|
||||
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars",
|
||||
"useBlurhash", "viewPagerOffScreenLimit" -> {
|
||||
"useBlurhash", "showCardsInTimelines", "confirmReblogs", "viewPagerOffScreenLimit" -> {
|
||||
restartActivitiesOnExit = true
|
||||
}
|
||||
"language" -> {
|
||||
|
@ -277,7 +277,7 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
|
||||
addTabAdapter.updateData(addableTabs)
|
||||
|
||||
maxTabsInfo.visible(addableTabs.size == 0 || currentTabs.size >= MAX_TAB_COUNT)
|
||||
currentTabsAdapter.setRemoveButtonVisible(currentTabs.size > MIN_TAB_COUNT);
|
||||
currentTabsAdapter.setRemoveButtonVisible(currentTabs.size > MIN_TAB_COUNT)
|
||||
}
|
||||
|
||||
override fun onStartDelete(viewHolder: RecyclerView.ViewHolder) {
|
||||
|
@ -0,0 +1,51 @@
|
||||
package com.keylesspalace.tusky.adapter
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.text.BidiFormatter
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Account
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper
|
||||
import com.keylesspalace.tusky.util.loadAvatar
|
||||
import com.keylesspalace.tusky.util.visible
|
||||
import kotlinx.android.synthetic.main.item_follow_request_notification.view.*
|
||||
|
||||
internal class FollowRequestViewHolder(itemView: View, private val showHeader: Boolean) : RecyclerView.ViewHolder(itemView) {
|
||||
private var id: String? = null
|
||||
private val animateAvatar: Boolean = PreferenceManager.getDefaultSharedPreferences(itemView.context)
|
||||
.getBoolean("animateGifAvatars", false)
|
||||
|
||||
fun setupWithAccount(account: Account, formatter: BidiFormatter?) {
|
||||
id = account.id
|
||||
val wrappedName = formatter?.unicodeWrap(account.name) ?: account.name
|
||||
val emojifiedName: CharSequence = CustomEmojiHelper.emojifyString(wrappedName, account.emojis, itemView)
|
||||
itemView.displayNameTextView.text = emojifiedName
|
||||
if (showHeader) {
|
||||
itemView.notificationTextView?.text = itemView.context.getString(R.string.notification_follow_request_format, emojifiedName)
|
||||
}
|
||||
itemView.notificationTextView?.visible(showHeader)
|
||||
val format = itemView.context.getString(R.string.status_username_format)
|
||||
val formattedUsername = String.format(format, account.username)
|
||||
itemView.usernameTextView.text = formattedUsername
|
||||
val avatarRadius = itemView.avatar.context.resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp)
|
||||
loadAvatar(account.avatar, itemView.avatar, avatarRadius, animateAvatar)
|
||||
}
|
||||
|
||||
fun setupActionListener(listener: AccountActionListener) {
|
||||
itemView.acceptButton.setOnClickListener {
|
||||
val position = adapterPosition
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onRespondToFollowRequest(true, id, position)
|
||||
}
|
||||
}
|
||||
itemView.rejectButton.setOnClickListener {
|
||||
val position = adapterPosition
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onRespondToFollowRequest(false, id, position)
|
||||
}
|
||||
}
|
||||
itemView.avatar.setOnClickListener { listener.onViewAccount(id) }
|
||||
}
|
||||
}
|
@ -18,19 +18,12 @@ package com.keylesspalace.tusky.adapter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper;
|
||||
import com.keylesspalace.tusky.util.ImageLoadingHelper;
|
||||
|
||||
public class FollowRequestsAdapter extends AccountAdapter {
|
||||
|
||||
@ -46,7 +39,7 @@ public class FollowRequestsAdapter extends AccountAdapter {
|
||||
case VIEW_TYPE_ACCOUNT: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_follow_request, parent, false);
|
||||
return new FollowRequestViewHolder(view);
|
||||
return new FollowRequestViewHolder(view, false);
|
||||
}
|
||||
case VIEW_TYPE_FOOTER: {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
@ -60,57 +53,8 @@ public class FollowRequestsAdapter extends AccountAdapter {
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
||||
if (getItemViewType(position) == VIEW_TYPE_ACCOUNT) {
|
||||
FollowRequestViewHolder holder = (FollowRequestViewHolder) viewHolder;
|
||||
holder.setupWithAccount(accountList.get(position));
|
||||
holder.setupWithAccount(accountList.get(position), null);
|
||||
holder.setupActionListener(accountActionListener);
|
||||
}
|
||||
}
|
||||
|
||||
static class FollowRequestViewHolder extends RecyclerView.ViewHolder {
|
||||
private ImageView avatar;
|
||||
private TextView username;
|
||||
private TextView displayName;
|
||||
private ImageButton accept;
|
||||
private ImageButton reject;
|
||||
private String id;
|
||||
private boolean animateAvatar;
|
||||
|
||||
FollowRequestViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
avatar = itemView.findViewById(R.id.avatar);
|
||||
username = itemView.findViewById(R.id.usernameTextView);
|
||||
displayName = itemView.findViewById(R.id.displayNameTextView);
|
||||
accept = itemView.findViewById(R.id.acceptButton);
|
||||
reject = itemView.findViewById(R.id.rejectButton);
|
||||
animateAvatar = PreferenceManager.getDefaultSharedPreferences(itemView.getContext())
|
||||
.getBoolean("animateGifAvatars", false);
|
||||
}
|
||||
|
||||
void setupWithAccount(Account account) {
|
||||
id = account.getId();
|
||||
CharSequence emojifiedName = CustomEmojiHelper.emojifyString(account.getName(), account.getEmojis(), displayName);
|
||||
displayName.setText(emojifiedName);
|
||||
String format = username.getContext().getString(R.string.status_username_format);
|
||||
String formattedUsername = String.format(format, account.getUsername());
|
||||
username.setText(formattedUsername);
|
||||
int avatarRadius = avatar.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.avatar_radius_48dp);
|
||||
ImageLoadingHelper.loadAvatar(account.getAvatar(), avatar, avatarRadius, animateAvatar);
|
||||
}
|
||||
|
||||
void setupActionListener(final AccountActionListener listener) {
|
||||
accept.setOnClickListener(v -> {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onRespondToFollowRequest(true, id, position);
|
||||
}
|
||||
});
|
||||
reject.setOnClickListener(v -> {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onRespondToFollowRequest(false, id, position);
|
||||
}
|
||||
});
|
||||
avatar.setOnClickListener(v -> listener.onViewAccount(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,10 @@ import com.keylesspalace.tusky.entity.Account;
|
||||
import com.keylesspalace.tusky.entity.Emoji;
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.keylesspalace.tusky.interfaces.LinkListener;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper;
|
||||
import com.keylesspalace.tusky.util.ImageLoadingHelper;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
@ -75,8 +77,9 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
private static final int VIEW_TYPE_STATUS = 0;
|
||||
private static final int VIEW_TYPE_STATUS_NOTIFICATION = 1;
|
||||
private static final int VIEW_TYPE_FOLLOW = 2;
|
||||
private static final int VIEW_TYPE_PLACEHOLDER = 3;
|
||||
private static final int VIEW_TYPE_UNKNOWN = 4;
|
||||
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 InputFilter[] COLLAPSE_INPUT_FILTER = new InputFilter[]{SmartLengthInputFilter.INSTANCE};
|
||||
private static final InputFilter[] NO_INPUT_FILTER = new InputFilter[0];
|
||||
@ -85,6 +88,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
private StatusDisplayOptions statusDisplayOptions;
|
||||
private StatusActionListener statusListener;
|
||||
private NotificationActionListener notificationActionListener;
|
||||
private AccountActionListener accountActionListener;
|
||||
private BidiFormatter bidiFormatter;
|
||||
private AdapterDataSource<NotificationViewData> dataSource;
|
||||
|
||||
@ -92,13 +96,15 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
AdapterDataSource<NotificationViewData> dataSource,
|
||||
StatusDisplayOptions statusDisplayOptions,
|
||||
StatusActionListener statusListener,
|
||||
NotificationActionListener notificationActionListener) {
|
||||
NotificationActionListener notificationActionListener,
|
||||
AccountActionListener accountActionListener) {
|
||||
|
||||
this.accountId = accountId;
|
||||
this.dataSource = dataSource;
|
||||
this.statusDisplayOptions = statusDisplayOptions;
|
||||
this.statusListener = statusListener;
|
||||
this.notificationActionListener = notificationActionListener;
|
||||
this.accountActionListener = accountActionListener;
|
||||
bidiFormatter = BidiFormatter.getInstance();
|
||||
}
|
||||
|
||||
@ -122,6 +128,11 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
.inflate(R.layout.item_follow, parent, false);
|
||||
return new FollowViewHolder(view, statusDisplayOptions);
|
||||
}
|
||||
case VIEW_TYPE_FOLLOW_REQUEST: {
|
||||
View view = inflater
|
||||
.inflate(R.layout.item_follow_request_notification, parent, false);
|
||||
return new FollowRequestViewHolder(view, true);
|
||||
}
|
||||
case VIEW_TYPE_PLACEHOLDER: {
|
||||
View view = inflater
|
||||
.inflate(R.layout.item_status_placeholder, parent, false);
|
||||
@ -218,6 +229,13 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VIEW_TYPE_FOLLOW_REQUEST: {
|
||||
if (payloadForHolder == null) {
|
||||
FollowRequestViewHolder holder = (FollowRequestViewHolder) viewHolder;
|
||||
holder.setupWithAccount(concreteNotificaton.getAccount(), bidiFormatter);
|
||||
holder.setupActionListener(accountActionListener);
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
@ -234,7 +252,9 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
mediaPreviewEnabled,
|
||||
statusDisplayOptions.useAbsoluteTime(),
|
||||
statusDisplayOptions.showBotOverlay(),
|
||||
statusDisplayOptions.useBlurhash()
|
||||
statusDisplayOptions.useBlurhash(),
|
||||
CardViewMode.NONE,
|
||||
statusDisplayOptions.confirmReblogs()
|
||||
);
|
||||
}
|
||||
|
||||
@ -259,6 +279,9 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||
case FOLLOW: {
|
||||
return VIEW_TYPE_FOLLOW;
|
||||
}
|
||||
case FOLLOW_REQUEST: {
|
||||
return VIEW_TYPE_FOLLOW_REQUEST;
|
||||
}
|
||||
default: {
|
||||
return VIEW_TYPE_UNKNOWN;
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper
|
||||
import com.keylesspalace.tusky.util.HtmlUtils
|
||||
import com.keylesspalace.tusky.util.visible
|
||||
import com.keylesspalace.tusky.viewdata.PollOptionViewData
|
||||
import com.keylesspalace.tusky.viewdata.buildDescription
|
||||
@ -36,12 +35,19 @@ class PollAdapter: RecyclerView.Adapter<PollViewHolder>() {
|
||||
|
||||
private var pollOptions: List<PollOptionViewData> = emptyList()
|
||||
private var voteCount: Int = 0
|
||||
private var votersCount: Int? = null
|
||||
private var mode = RESULT
|
||||
private var emojis: List<Emoji> = emptyList()
|
||||
|
||||
fun setup(options: List<PollOptionViewData>, voteCount: Int, emojis: List<Emoji>, mode: Int) {
|
||||
fun setup(
|
||||
options: List<PollOptionViewData>,
|
||||
voteCount: Int,
|
||||
votersCount: Int?,
|
||||
emojis: List<Emoji>,
|
||||
mode: Int) {
|
||||
this.pollOptions = options
|
||||
this.voteCount = voteCount
|
||||
this.votersCount = votersCount
|
||||
this.emojis = emojis
|
||||
this.mode = mode
|
||||
notifyDataSetChanged()
|
||||
@ -71,7 +77,7 @@ class PollAdapter: RecyclerView.Adapter<PollViewHolder>() {
|
||||
|
||||
when(mode) {
|
||||
RESULT -> {
|
||||
val percent = calculatePercent(option.votesCount, voteCount)
|
||||
val percent = calculatePercent(option.votesCount, votersCount, voteCount)
|
||||
val emojifiedPollOptionText = CustomEmojiHelper.emojifyText(buildDescription(option.title, percent, holder.resultTextView.context), emojis, holder.resultTextView)
|
||||
holder.resultTextView.text = EmojiCompat.get().process(emojifiedPollOptionText)
|
||||
|
||||
|
@ -8,31 +8,38 @@ import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.entity.Attachment;
|
||||
import com.keylesspalace.tusky.entity.Attachment.Focus;
|
||||
import com.keylesspalace.tusky.entity.Attachment.MetaData;
|
||||
import com.keylesspalace.tusky.entity.Card;
|
||||
import com.keylesspalace.tusky.entity.Emoji;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.CustomEmojiHelper;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
import com.keylesspalace.tusky.util.ImageLoadingHelper;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
||||
@ -92,6 +99,12 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
private TextView pollDescription;
|
||||
private Button pollButton;
|
||||
|
||||
private LinearLayout cardView;
|
||||
private LinearLayout cardInfo;
|
||||
private ImageView cardImage;
|
||||
private TextView cardTitle;
|
||||
private TextView cardDescription;
|
||||
private TextView cardUrl;
|
||||
private PollAdapter pollAdapter;
|
||||
|
||||
private SimpleDateFormat shortSdf;
|
||||
@ -152,6 +165,13 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
pollDescription = itemView.findViewById(R.id.status_poll_description);
|
||||
pollButton = itemView.findViewById(R.id.status_poll_button);
|
||||
|
||||
cardView = itemView.findViewById(R.id.status_card_view);
|
||||
cardInfo = itemView.findViewById(R.id.card_info);
|
||||
cardImage = itemView.findViewById(R.id.card_image);
|
||||
cardTitle = itemView.findViewById(R.id.card_title);
|
||||
cardDescription = itemView.findViewById(R.id.card_description);
|
||||
cardUrl = itemView.findViewById(R.id.card_link);
|
||||
|
||||
pollAdapter = new PollAdapter();
|
||||
pollOptions.setAdapter(pollAdapter);
|
||||
pollOptions.setLayoutManager(new LinearLayoutManager(pollOptions.getContext()));
|
||||
@ -200,7 +220,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
contentWarningDescription.setVisibility(View.VISIBLE);
|
||||
contentWarningButton.setVisibility(View.VISIBLE);
|
||||
setContentWarningButtonText(expanded);
|
||||
contentWarningButton.setOnClickListener( view -> {
|
||||
contentWarningButton.setOnClickListener(view -> {
|
||||
contentWarningDescription.invalidate();
|
||||
if (getAdapterPosition() != RecyclerView.NO_POSITION) {
|
||||
listener.onExpandedChange(!expanded, getAdapterPosition());
|
||||
@ -218,7 +238,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
}
|
||||
|
||||
private void setContentWarningButtonText(boolean expanded) {
|
||||
if(expanded) {
|
||||
if (expanded) {
|
||||
contentWarningButton.setText(R.string.status_content_warning_show_less);
|
||||
} else {
|
||||
contentWarningButton.setText(R.string.status_content_warning_show_more);
|
||||
@ -673,8 +693,12 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
sensitiveMediaShow.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
protected void setupButtons(final StatusActionListener listener, final String accountId,
|
||||
final boolean isNotestock, final String acct) {
|
||||
protected void setupButtons(final StatusActionListener listener,
|
||||
final String accountId,
|
||||
final String statusContent,
|
||||
final boolean isNotestock,
|
||||
final String acct,
|
||||
StatusDisplayOptions statusDisplayOptions) {
|
||||
|
||||
avatar.setOnClickListener(v -> {
|
||||
if (isNotestock) {
|
||||
@ -702,9 +726,18 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
replyButton.setClickable(!isNotestock);
|
||||
if (reblogButton != null) {
|
||||
reblogButton.setEventListener((button, buttonState) -> {
|
||||
// return true to play animaion
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onReblog(buttonState, position);
|
||||
if (statusDisplayOptions.confirmReblogs()) {
|
||||
showConfirmReblogDialog(listener, statusContent, buttonState, position);
|
||||
return false;
|
||||
} else {
|
||||
listener.onReblog(!buttonState, position);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -712,8 +745,9 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
favouriteButton.setEventListener((button, buttonState) -> {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onFavourite(buttonState, position);
|
||||
listener.onFavourite(!buttonState, position);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
favouriteButton.setEnabled(!isNotestock);
|
||||
@ -731,8 +765,9 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
bookmarkButton.setEventListener((button, buttonState) -> {
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onBookmark(buttonState, position);
|
||||
listener.onBookmark(!buttonState, position);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
moreButton.setOnClickListener(v -> {
|
||||
@ -757,6 +792,23 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
itemView.setOnClickListener(viewThreadListener);
|
||||
}
|
||||
|
||||
private void showConfirmReblogDialog(StatusActionListener listener,
|
||||
String statusContent,
|
||||
boolean buttonState,
|
||||
int position) {
|
||||
int okButtonTextId = buttonState ? R.string.action_unreblog : R.string.action_reblog;
|
||||
new AlertDialog.Builder(reblogButton.getContext())
|
||||
.setMessage(statusContent)
|
||||
.setPositiveButton(okButtonTextId, (__, ___) -> {
|
||||
listener.onReblog(!buttonState, position);
|
||||
if (!buttonState) {
|
||||
// Play animation only when it's reblog, not unreblog
|
||||
reblogButton.playAnimation();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
public void setupWithStatus(StatusViewData.Concrete status, final StatusActionListener listener,
|
||||
StatusDisplayOptions statusDisplayOptions) {
|
||||
this.setupWithStatus(status, listener, statusDisplayOptions, null);
|
||||
@ -799,8 +851,13 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
hideSensitiveMediaWarning();
|
||||
}
|
||||
|
||||
setupButtons(listener, status.getSenderId(), status.isNotestock(), status.getNickname());
|
||||
setRebloggingEnabled(status.getRebloggingEnabled() && !status.isNotestock(), status.getVisibility());
|
||||
if (cardView != null) {
|
||||
setupCard(status, statusDisplayOptions.cardViewMode());
|
||||
}
|
||||
|
||||
setupButtons(listener, status.getSenderId(), status.getContent().toString(),
|
||||
status.isNotestock(), status.getNickname(), statusDisplayOptions);
|
||||
setRebloggingEnabled(status.getRebloggingEnabled(), status.getVisibility());
|
||||
setQuoteEnabled(status.getRebloggingEnabled() && !status.isNotestock(), status.getVisibility());
|
||||
|
||||
setSpoilerAndContent(status.isExpanded(), status.getContent(), status.getSpoilerText(), status.getMentions(), status.getStatusEmojis(), status.getPoll(), statusDisplayOptions, listener, status.getQuote() != null);
|
||||
@ -934,7 +991,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
List<PollOptionViewData> options = poll.getOptions();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (i < options.size()) {
|
||||
int percent = PollViewDataKt.calculatePercent(options.get(i).getVotesCount(), poll.getVotesCount());
|
||||
int percent = PollViewDataKt.calculatePercent(options.get(i).getVotesCount(), poll.getVotersCount(), poll.getVotesCount());
|
||||
args[i] = buildDescription(options.get(i).getTitle(), percent, context);
|
||||
} else {
|
||||
args[i] = "";
|
||||
@ -949,7 +1006,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
protected CharSequence getFavsText(Context context, int count) {
|
||||
if (count > 0) {
|
||||
String countString = numberFormat.format(count);
|
||||
return HtmlUtils.fromHtml(context.getResources().getQuantityString(R.plurals.favs, count, countString));
|
||||
return HtmlCompat.fromHtml(context.getResources().getQuantityString(R.plurals.favs, count, countString), HtmlCompat.FROM_HTML_MODE_LEGACY);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
@ -958,7 +1015,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
protected CharSequence getReblogsText(Context context, int count) {
|
||||
if (count > 0) {
|
||||
String countString = numberFormat.format(count);
|
||||
return HtmlUtils.fromHtml(context.getResources().getQuantityString(R.plurals.reblogs, count, countString));
|
||||
return HtmlCompat.fromHtml(context.getResources().getQuantityString(R.plurals.reblogs, count, countString), HtmlCompat.FROM_HTML_MODE_LEGACY);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
@ -977,12 +1034,12 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
if (expired || poll.getVoted()) {
|
||||
// no voting possible
|
||||
pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), emojis, PollAdapter.RESULT);
|
||||
pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), poll.getVotersCount(), emojis, PollAdapter.RESULT);
|
||||
|
||||
pollButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
// voting possible
|
||||
pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), emojis, poll.getMultiple() ? PollAdapter.MULTIPLE : PollAdapter.SINGLE);
|
||||
pollAdapter.setup(poll.getOptions(), poll.getVotesCount(), poll.getVotersCount(), emojis, poll.getMultiple() ? PollAdapter.MULTIPLE : PollAdapter.SINGLE);
|
||||
|
||||
pollButton.setVisibility(View.VISIBLE);
|
||||
|
||||
@ -1009,8 +1066,14 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
private CharSequence getPollInfoText(long timestamp, PollViewData poll,
|
||||
StatusDisplayOptions statusDisplayOptions,
|
||||
Context context) {
|
||||
String votes = numberFormat.format(poll.getVotesCount());
|
||||
String votesText = context.getResources().getQuantityString(R.plurals.poll_info_votes, poll.getVotesCount(), votes);
|
||||
String votesText;
|
||||
if(poll.getVotersCount() == null) {
|
||||
String voters = numberFormat.format(poll.getVotesCount());
|
||||
votesText = context.getResources().getQuantityString(R.plurals.poll_info_votes, poll.getVotesCount(), voters);
|
||||
} else {
|
||||
String voters = numberFormat.format(poll.getVotersCount());
|
||||
votesText = context.getResources().getQuantityString(R.plurals.poll_info_people, poll.getVotersCount(), voters);
|
||||
}
|
||||
CharSequence pollDurationInfo;
|
||||
if (poll.getExpired()) {
|
||||
pollDurationInfo = context.getString(R.string.poll_info_closed);
|
||||
@ -1028,6 +1091,80 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||
return pollDescription.getContext().getString(R.string.poll_info_format, votesText, pollDurationInfo);
|
||||
}
|
||||
|
||||
protected void setupCard(StatusViewData.Concrete status, CardViewMode cardViewMode) {
|
||||
if (cardViewMode != CardViewMode.NONE && status.getAttachments().size() == 0 && status.getCard() != null && !TextUtils.isEmpty(status.getCard().getUrl())) {
|
||||
final Card card = status.getCard();
|
||||
cardView.setVisibility(View.VISIBLE);
|
||||
cardTitle.setText(card.getTitle());
|
||||
if (TextUtils.isEmpty(card.getDescription()) && TextUtils.isEmpty(card.getAuthorName())) {
|
||||
cardDescription.setVisibility(View.GONE);
|
||||
} else {
|
||||
cardDescription.setVisibility(View.VISIBLE);
|
||||
if (TextUtils.isEmpty(card.getDescription())) {
|
||||
cardDescription.setText(card.getAuthorName());
|
||||
} else {
|
||||
cardDescription.setText(card.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
cardUrl.setText(card.getUrl());
|
||||
|
||||
if (!TextUtils.isEmpty(card.getImage())) {
|
||||
|
||||
int topLeftRadius = 0;
|
||||
int topRightRadius = 0;
|
||||
int bottomRightRadius = 0;
|
||||
int bottomLeftRadius = 0;
|
||||
|
||||
int radius = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_radius);
|
||||
|
||||
if (card.getWidth() > card.getHeight()) {
|
||||
cardView.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
cardImage.getLayoutParams().height = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_image_vertical_height);
|
||||
cardImage.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardInfo.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardInfo.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
topLeftRadius = radius;
|
||||
topRightRadius = radius;
|
||||
} else {
|
||||
cardView.setOrientation(LinearLayout.HORIZONTAL);
|
||||
cardImage.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardImage.getLayoutParams().width = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_image_horizontal_width);
|
||||
cardInfo.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
cardInfo.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
topLeftRadius = radius;
|
||||
bottomLeftRadius = radius;
|
||||
}
|
||||
|
||||
|
||||
Glide.with(cardImage)
|
||||
.load(card.getImage())
|
||||
.transform(
|
||||
new CenterCrop(),
|
||||
new GranularRoundedCorners(topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius)
|
||||
)
|
||||
.into(cardImage);
|
||||
} else {
|
||||
cardView.setOrientation(LinearLayout.HORIZONTAL);
|
||||
cardImage.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardImage.getLayoutParams().width = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_image_horizontal_width);
|
||||
cardInfo.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
cardInfo.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardImage.setImageResource(R.drawable.card_image_placeholder);
|
||||
}
|
||||
|
||||
cardView.setOnClickListener(v -> LinkHelper.openLink(card.getUrl(), v.getContext()));
|
||||
cardView.setClipToOutline(true);
|
||||
} else {
|
||||
cardView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatDuration(double durationInSeconds) {
|
||||
int seconds = (int) Math.round(durationInSeconds) % 60;
|
||||
int minutes = (int) durationInSeconds % 3600 / 60;
|
||||
|
@ -5,26 +5,19 @@ import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners;
|
||||
import com.keylesspalace.tusky.R;
|
||||
import com.keylesspalace.tusky.ViewThreadActivity;
|
||||
import com.keylesspalace.tusky.entity.Card;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
@ -37,27 +30,13 @@ import java.util.regex.Pattern;
|
||||
class StatusDetailedViewHolder extends StatusBaseViewHolder {
|
||||
private TextView reblogs;
|
||||
private TextView favourites;
|
||||
private LinearLayout cardView;
|
||||
private LinearLayout cardInfo;
|
||||
private ImageView cardImage;
|
||||
private TextView cardTitle;
|
||||
private TextView cardDescription;
|
||||
private TextView cardUrl;
|
||||
private View infoDivider;
|
||||
|
||||
StatusDetailedViewHolder(View view) {
|
||||
super(view);
|
||||
reblogs = view.findViewById(R.id.status_reblogs);
|
||||
favourites = view.findViewById(R.id.status_favourites);
|
||||
cardView = view.findViewById(R.id.card_view);
|
||||
cardInfo = view.findViewById(R.id.card_info);
|
||||
cardImage = view.findViewById(R.id.card_image);
|
||||
cardTitle = view.findViewById(R.id.card_title);
|
||||
cardDescription = view.findViewById(R.id.card_description);
|
||||
cardUrl = view.findViewById(R.id.card_link);
|
||||
infoDivider = view.findViewById(R.id.status_info_divider);
|
||||
|
||||
cardView.setClipToOutline(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -131,6 +110,7 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder {
|
||||
StatusDisplayOptions statusDisplayOptions,
|
||||
@Nullable Object payloads) {
|
||||
super.setupWithStatus(status, listener, statusDisplayOptions, payloads);
|
||||
setupCard(status, CardViewMode.FULL_WIDTH); // Always show card for detailed status
|
||||
if (payloads == null) {
|
||||
setReblogAndFavCount(status.getReblogsCount(), status.getFavouritesCount(), listener);
|
||||
|
||||
@ -149,97 +129,6 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder {
|
||||
|
||||
content.setOnLongClickListener(longClickListener);
|
||||
contentWarningDescription.setOnLongClickListener(longClickListener);
|
||||
|
||||
if (status.getAttachments().size() == 0 && status.getCard() != null && !TextUtils.isEmpty(status.getCard().getUrl())) {
|
||||
final Card card = status.getCard();
|
||||
cardView.setVisibility(View.VISIBLE);
|
||||
cardTitle.setText(card.getTitle());
|
||||
if (TextUtils.isEmpty(card.getDescription()) && TextUtils.isEmpty(card.getAuthorName())) {
|
||||
cardDescription.setVisibility(View.GONE);
|
||||
} else {
|
||||
cardDescription.setVisibility(View.VISIBLE);
|
||||
if (TextUtils.isEmpty(card.getDescription())) {
|
||||
cardDescription.setText(card.getAuthorName());
|
||||
} else {
|
||||
cardDescription.setText(card.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
cardUrl.setText(card.getUrl());
|
||||
|
||||
if (!TextUtils.isEmpty(card.getImage())) {
|
||||
|
||||
int topLeftRadius = 0;
|
||||
int topRightRadius = 0;
|
||||
int bottomRightRadius = 0;
|
||||
int bottomLeftRadius = 0;
|
||||
|
||||
int radius = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_radius);
|
||||
|
||||
if (card.getWidth() > card.getHeight()) {
|
||||
cardView.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
cardImage.getLayoutParams().height = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_image_vertical_height);
|
||||
cardImage.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardInfo.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardInfo.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
topLeftRadius = radius;
|
||||
topRightRadius = radius;
|
||||
} else {
|
||||
cardView.setOrientation(LinearLayout.HORIZONTAL);
|
||||
cardImage.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardImage.getLayoutParams().width = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_image_horizontal_width);
|
||||
cardInfo.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
cardInfo.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
topLeftRadius = radius;
|
||||
bottomLeftRadius = radius;
|
||||
}
|
||||
|
||||
|
||||
Glide.with(cardImage)
|
||||
.load(card.getImage())
|
||||
.transform(
|
||||
new CenterCrop(),
|
||||
new GranularRoundedCorners(topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius)
|
||||
)
|
||||
.into(cardImage);
|
||||
|
||||
} else {
|
||||
cardView.setOrientation(LinearLayout.HORIZONTAL);
|
||||
cardImage.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
cardImage.getLayoutParams().width = cardImage.getContext().getResources()
|
||||
.getDimensionPixelSize(R.dimen.card_image_horizontal_width);
|
||||
cardInfo.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
cardInfo.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
|
||||
cardImage.setImageResource(R.drawable.card_image_placeholder);
|
||||
|
||||
}
|
||||
|
||||
cardView.setOnClickListener(v -> {
|
||||
String url = card.getUrl();
|
||||
String regex = ".*/users/[^/]+/statuses/([0-9]+)";
|
||||
String replace = "$1";
|
||||
Pattern p = Pattern.compile(regex);
|
||||
Matcher m = p.matcher(url);
|
||||
if (m.find()) {
|
||||
String id = m.replaceAll(replace);
|
||||
Intent intent = new Intent(v.getContext(), ViewThreadActivity.class);
|
||||
intent.putExtra("id", id);
|
||||
intent.putExtra("url", url);
|
||||
v.getContext().startActivity(intent);
|
||||
} else {
|
||||
LinkHelper.openLink(url, v.getContext());
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
cardView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,9 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
|
||||
mediaPreviewEnabled,
|
||||
statusDisplayOptions.useAbsoluteTime(),
|
||||
statusDisplayOptions.showBotOverlay(),
|
||||
statusDisplayOptions.useBlurhash()
|
||||
statusDisplayOptions.useBlurhash(),
|
||||
statusDisplayOptions.cardViewMode(),
|
||||
statusDisplayOptions.confirmReblogs()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import com.keylesspalace.tusky.entity.Status
|
||||
data class FavoriteEvent(val statusId: String, val favourite: Boolean) : Dispatchable
|
||||
data class ReblogEvent(val statusId: String, val reblog: Boolean) : Dispatchable
|
||||
data class BookmarkEvent(val statusId: String, val bookmark: Boolean) : Dispatchable
|
||||
data class MuteConversationEvent(val statusId: String, val mute: Boolean) : Dispatchable
|
||||
data class UnfollowEvent(val accountId: String) : Dispatchable
|
||||
data class BlockEvent(val accountId: String) : Dispatchable
|
||||
data class MuteEvent(val accountId: String) : Dispatchable
|
||||
|
@ -252,15 +252,14 @@ class ComposeActivity : BaseActivity(),
|
||||
if (action != null && action == Intent.ACTION_SEND) {
|
||||
val subject = intent.getStringExtra(Intent.EXTRA_SUBJECT)
|
||||
val text = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||
val shareBody = if (subject != null && text != null) {
|
||||
if (subject != text && !text.contains(subject)) {
|
||||
String.format("%s\n%s", subject, text)
|
||||
} else {
|
||||
text
|
||||
}
|
||||
} else text ?: subject
|
||||
val shareBody = text ?: subject
|
||||
|
||||
if (shareBody != null) {
|
||||
if (!subject.isNullOrBlank() && subject !in shareBody) {
|
||||
composeContentWarningField.setText(subject)
|
||||
viewModel.showContentWarning.value = true
|
||||
}
|
||||
|
||||
val start = composeEditField.selectionStart.coerceAtLeast(0)
|
||||
val end = composeEditField.selectionEnd.coerceAtLeast(0)
|
||||
val left = min(start, end)
|
||||
|
@ -271,7 +271,7 @@ class ComposeViewModel
|
||||
text,
|
||||
spoilerText,
|
||||
statusVisibility.value!!.serverString(),
|
||||
mediaUris.isNotEmpty() && markMediaAsSensitive.value!!,
|
||||
mediaUris.isNotEmpty() && (markMediaAsSensitive.value!! || showContentWarning.value!!),
|
||||
mediaIds,
|
||||
mediaUris.map { it.toString() },
|
||||
mediaDescriptions,
|
||||
|
@ -18,26 +18,19 @@ package com.keylesspalace.tusky.components.compose.view
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RadioGroup
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import kotlinx.android.synthetic.main.view_compose_options.view.*
|
||||
|
||||
|
||||
class ComposeOptionsView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
class ComposeOptionsView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : RadioGroup(context, attrs) {
|
||||
|
||||
var listener: ComposeOptionsListener? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.view_compose_options, this)
|
||||
|
||||
publicRadioButton.setButtonDrawable(R.drawable.ic_public_24dp)
|
||||
unlistedRadioButton.setButtonDrawable(R.drawable.ic_lock_open_24dp)
|
||||
privateRadioButton.setButtonDrawable(R.drawable.ic_lock_outline_24dp)
|
||||
unleakableRadioButton.setButtonDrawable(R.drawable.ic_low_vision_24dp)
|
||||
directRadioButton.setButtonDrawable(R.drawable.ic_email_24dp)
|
||||
|
||||
visibilityRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||
setOnCheckedChangeListener { _, checkedId ->
|
||||
val visibility = when (checkedId) {
|
||||
R.id.publicRadioButton ->
|
||||
Status.Visibility.PUBLIC
|
||||
@ -80,7 +73,7 @@ class ComposeOptionsView @JvmOverloads constructor(context: Context, attrs: Attr
|
||||
|
||||
}
|
||||
|
||||
visibilityRadioGroup.check(selectedButton)
|
||||
check(selectedButton)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -192,6 +192,9 @@ public class ComposeScheduleView extends ConstraintLayout {
|
||||
private void onDateSet(long selection) {
|
||||
initializeSuggestedTime();
|
||||
Calendar newDate = getCalendar();
|
||||
// working around bug in DatePicker where date is UTC #1720
|
||||
// see https://github.com/material-components/material-components-android/issues/882
|
||||
newDate.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
newDate.setTimeInMillis(selection);
|
||||
scheduleDateTime.set(newDate.get(Calendar.YEAR), newDate.get(Calendar.MONTH), newDate.get(Calendar.DATE));
|
||||
openPickTimeDialog();
|
||||
|
@ -157,6 +157,7 @@ data class ConversationStatusEntity(
|
||||
mentions = mentions,
|
||||
application = null,
|
||||
pinned = false,
|
||||
muted = false,
|
||||
poll = poll,
|
||||
card = null,
|
||||
quote = null)
|
||||
|
@ -104,7 +104,8 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
|
||||
hideSensitiveMediaWarning();
|
||||
}
|
||||
|
||||
setupButtons(listener, account.getId(), false, account.getUsername());
|
||||
setupButtons(listener, account.getId(), status.getContent().toString(),
|
||||
false, account.getUsername(), statusDisplayOptions);
|
||||
|
||||
setSpoilerAndContent(status.getExpanded(), status.getContent(), status.getSpoilerText(),
|
||||
status.getMentions(), status.getEmojis(),
|
||||
|
@ -36,10 +36,7 @@ import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.fragment.SFragment
|
||||
import com.keylesspalace.tusky.interfaces.ReselectableFragment
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener
|
||||
import com.keylesspalace.tusky.util.NetworkState
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import kotlinx.android.synthetic.main.fragment_timeline.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -68,7 +65,9 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable, Res
|
||||
mediaPreviewEnabled = accountManager.activeAccount?.mediaPreviewEnabled ?: true,
|
||||
useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false),
|
||||
showBotOverlay = preferences.getBoolean("showBotOverlay", true),
|
||||
useBlurhash = preferences.getBoolean("useBlurhash", true)
|
||||
useBlurhash = preferences.getBoolean("useBlurhash", true),
|
||||
cardViewMode = CardViewMode.NONE,
|
||||
confirmReblogs = preferences.getBoolean("confirmReblogs", false)
|
||||
)
|
||||
|
||||
|
||||
|
@ -43,10 +43,7 @@ import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import com.keylesspalace.tusky.util.show
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.keylesspalace.tusky.viewdata.AttachmentViewData
|
||||
import kotlinx.android.synthetic.main.fragment_report_statuses.*
|
||||
import javax.inject.Inject
|
||||
@ -119,7 +116,9 @@ class ReportStatusesFragment : Fragment(), Injectable, AdapterHandler {
|
||||
mediaPreviewEnabled = accountManager.activeAccount?.mediaPreviewEnabled ?: true,
|
||||
useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false),
|
||||
showBotOverlay = false,
|
||||
useBlurhash = preferences.getBoolean("useBlurhash", true)
|
||||
useBlurhash = preferences.getBoolean("useBlurhash", true),
|
||||
cardViewMode = CardViewMode.NONE,
|
||||
confirmReblogs = preferences.getBoolean("confirmReblogs", false)
|
||||
)
|
||||
|
||||
adapter = StatusesAdapter(statusDisplayOptions,
|
||||
|
@ -243,7 +243,7 @@ class SearchViewModel @Inject constructor(
|
||||
return accountManager.getAllAccountsOrderedByActive()
|
||||
}
|
||||
|
||||
fun muteAcount(accountId: String) {
|
||||
fun muteAccount(accountId: String) {
|
||||
timelineCases.mute(accountId)
|
||||
}
|
||||
|
||||
@ -263,6 +263,18 @@ class SearchViewModel @Inject constructor(
|
||||
search(currentQuery)
|
||||
}
|
||||
|
||||
fun muteConversation(status: Pair<Status, StatusViewData.Concrete>, mute: Boolean) {
|
||||
val idx = loadedStatuses.indexOf(status)
|
||||
if (idx >= 0) {
|
||||
val newPair = Pair(status.first, StatusViewData.Builder(status.second).setMuted(mute).createStatusViewData())
|
||||
loadedStatuses[idx] = newPair
|
||||
repoResultStatus.value?.refresh?.invoke()
|
||||
}
|
||||
timelineCases.muteConversation(status.first, mute)
|
||||
.onErrorReturnItem(status.first)
|
||||
.subscribe()
|
||||
.autoDispose()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "SearchViewModel"
|
||||
|
@ -49,8 +49,10 @@ import com.keylesspalace.tusky.components.search.adapter.SearchStatusesAdapter
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.entity.Status.Mention
|
||||
import com.keylesspalace.tusky.interfaces.AccountSelectionListener
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener
|
||||
import com.keylesspalace.tusky.util.CardViewMode
|
||||
import com.keylesspalace.tusky.util.NetworkState
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions
|
||||
import com.keylesspalace.tusky.viewdata.AttachmentViewData
|
||||
@ -70,7 +72,7 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
get() = viewModel.statuses
|
||||
|
||||
private val searchAdapter
|
||||
get() = super.adapter as SearchStatusesAdapter
|
||||
get() = super.adapter as SearchStatusesAdapter
|
||||
|
||||
override fun createAdapter(): PagedListAdapter<Pair<Status, StatusViewData.Concrete>, *> {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(searchRecyclerView.context)
|
||||
@ -79,7 +81,9 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
mediaPreviewEnabled = viewModel.mediaPreviewEnabled,
|
||||
useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false),
|
||||
showBotOverlay = preferences.getBoolean("showBotOverlay", true),
|
||||
useBlurhash = preferences.getBoolean("useBlurhash", true)
|
||||
useBlurhash = preferences.getBoolean("useBlurhash", true),
|
||||
cardViewMode = CardViewMode.NONE,
|
||||
confirmReblogs = preferences.getBoolean("confirmReblogs", false)
|
||||
)
|
||||
|
||||
searchRecyclerView.addItemDecoration(DividerItemDecoration(searchRecyclerView.context, DividerItemDecoration.VERTICAL))
|
||||
@ -250,12 +254,9 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
val loggedInAccountId = viewModel.activeAccount?.accountId
|
||||
|
||||
val popup = PopupMenu(view.context, view)
|
||||
val statusIsByCurrentUser = loggedInAccountId?.equals(accountId) == true
|
||||
// Give a different menu depending on whether this is the user's own toot or not.
|
||||
if (loggedInAccountId == null || loggedInAccountId != accountId) {
|
||||
popup.inflate(R.menu.status_more)
|
||||
val menu = popup.menu
|
||||
menu.findItem(R.id.status_download_media).isVisible = status.attachments.isNotEmpty()
|
||||
} else {
|
||||
if (statusIsByCurrentUser) {
|
||||
popup.inflate(R.menu.status_more_for_user)
|
||||
val menu = popup.menu
|
||||
menu.findItem(R.id.status_open_as).isVisible = !statusUrl.isNullOrBlank()
|
||||
@ -273,6 +274,10 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
Status.Visibility.UNKNOWN, Status.Visibility.UNLEAKABLE, Status.Visibility.DIRECT -> {
|
||||
} //Ignore
|
||||
}
|
||||
} else {
|
||||
popup.inflate(R.menu.status_more)
|
||||
val menu = popup.menu
|
||||
menu.findItem(R.id.status_download_media).isVisible = status.attachments.isNotEmpty()
|
||||
}
|
||||
|
||||
val openAsItem = popup.menu.findItem(R.id.status_open_as)
|
||||
@ -288,6 +293,19 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
}
|
||||
openAsItem.title = openAsTitle
|
||||
|
||||
val mutable = statusIsByCurrentUser || accountIsInMentions(viewModel.activeAccount, status.mentions)
|
||||
val muteConversationItem = popup.menu.findItem(R.id.status_mute_conversation).apply {
|
||||
isVisible = mutable
|
||||
}
|
||||
if (mutable) {
|
||||
muteConversationItem.setTitle(
|
||||
if (status.muted == true) {
|
||||
R.string.action_unmute_conversation
|
||||
} else {
|
||||
R.string.action_mute_conversation
|
||||
})
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.status_share_content -> {
|
||||
@ -325,12 +343,18 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
requestDownloadAllMedia(status)
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
R.id.status_mute_conversation -> {
|
||||
searchAdapter.getItem(position)?.let { foundStatus ->
|
||||
viewModel.muteConversation(foundStatus, status.muted != true)
|
||||
}
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
R.id.status_mute -> {
|
||||
viewModel.muteAcount(accountId)
|
||||
onMute(accountId, accountUsername)
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
R.id.status_block -> {
|
||||
viewModel.blockAccount(accountId)
|
||||
onBlock(accountId, accountUsername)
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
R.id.status_report -> {
|
||||
@ -363,6 +387,28 @@ open class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.C
|
||||
popup.show()
|
||||
}
|
||||
|
||||
private fun onBlock(accountId: String, accountUsername: String) {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setMessage(getString(R.string.dialog_block_warning, accountUsername))
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> viewModel.blockAccount(accountId) }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun onMute(accountId: String, accountUsername: String) {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setMessage(getString(R.string.dialog_mute_warning, accountUsername))
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> viewModel.muteAccount(accountId) }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun accountIsInMentions(account: AccountEntity?, mentions: Array<Mention>): Boolean {
|
||||
return mentions.firstOrNull {
|
||||
account?.username == it.username && account.domain == Uri.parse(it.url)?.host
|
||||
} != null
|
||||
}
|
||||
|
||||
private fun showOpenAsDialog(statusUrl: String, dialogTitle: CharSequence) {
|
||||
bottomSheetActivity?.showAccountChooserDialog(dialogTitle, false, object : AccountSelectionListener {
|
||||
override fun onAccountSelected(account: AccountEntity) {
|
||||
|
@ -39,6 +39,7 @@ data class AccountEntity(@field:PrimaryKey(autoGenerate = true) var id: Long,
|
||||
var notificationsEnabled: Boolean = true,
|
||||
var notificationsMentioned: Boolean = true,
|
||||
var notificationsFollowed: Boolean = true,
|
||||
var notificationsFollowRequested: Boolean = false,
|
||||
var notificationsReblogged: Boolean = true,
|
||||
var notificationsFavorited: Boolean = true,
|
||||
var notificationsPolls: Boolean = true,
|
||||
@ -54,7 +55,7 @@ data class AccountEntity(@field:PrimaryKey(autoGenerate = true) var id: Long,
|
||||
var activeNotifications: String = "[]",
|
||||
var emojis: List<Emoji> = emptyList(),
|
||||
var tabPreferences: List<TabData> = defaultTabs(),
|
||||
var notificationsFilter: String = "[]") {
|
||||
var notificationsFilter: String = "[\"follow_request\"]") {
|
||||
|
||||
val identifier: String
|
||||
get() = "$domain:$accountId"
|
||||
|
@ -30,7 +30,7 @@ import androidx.annotation.NonNull;
|
||||
|
||||
@Database(entities = {TootEntity.class, AccountEntity.class, InstanceEntity.class, TimelineStatusEntity.class,
|
||||
TimelineAccountEntity.class, ConversationEntity.class
|
||||
}, version = 21)
|
||||
}, version = 23)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
|
||||
public abstract TootDao tootDao();
|
||||
@ -326,4 +326,18 @@ public abstract class AppDatabase extends RoomDatabase {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
public static final Migration MIGRATION_21_22 = new Migration(21, 22) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `notificationsFollowRequested` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
};
|
||||
|
||||
public static final Migration MIGRATION_22_23 = new Migration(22, 23) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `TimelineStatusEntity` ADD COLUMN `muted` INTEGER");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
package com.keylesspalace.tusky.db
|
||||
|
||||
import android.text.Spanned
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.text.toHtml
|
||||
import androidx.room.TypeConverter
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
@ -27,7 +29,6 @@ import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.json.SpannedTypeAdapter
|
||||
import com.keylesspalace.tusky.util.HtmlUtils
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
@ -128,7 +129,7 @@ class Converters {
|
||||
if(spanned == null) {
|
||||
return null
|
||||
}
|
||||
return HtmlUtils.toHtml(spanned)
|
||||
return spanned.toHtml()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
@ -136,7 +137,7 @@ class Converters {
|
||||
if(spannedString == null) {
|
||||
return null
|
||||
}
|
||||
return HtmlUtils.fromHtml(spannedString)
|
||||
return spannedString.parseAsHtml()
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
|
@ -51,7 +51,8 @@ data class TimelineStatusEntity(
|
||||
val application: String?,
|
||||
val reblogServerId: String?, // if it has a reblogged status, it's id is stored here
|
||||
val reblogAccountId: String?,
|
||||
val poll: String?
|
||||
val poll: String?,
|
||||
val muted: Boolean?
|
||||
)
|
||||
|
||||
@Entity(
|
||||
|
@ -29,8 +29,6 @@ import com.keylesspalace.tusky.db.AppDatabase
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.network.TimelineCases
|
||||
import com.keylesspalace.tusky.network.TimelineCasesImpl
|
||||
import com.keylesspalace.tusky.util.HtmlConverter
|
||||
import com.keylesspalace.tusky.util.HtmlConverterImpl
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Singleton
|
||||
@ -79,13 +77,9 @@ class AppModule {
|
||||
AppDatabase.MIGRATION_11_12, AppDatabase.MIGRATION_12_13, AppDatabase.MIGRATION_10_13,
|
||||
AppDatabase.MIGRATION_13_14, AppDatabase.MIGRATION_14_15, AppDatabase.MIGRATION_15_16,
|
||||
AppDatabase.MIGRATION_16_17, AppDatabase.MIGRATION_17_18, AppDatabase.MIGRATION_18_19,
|
||||
AppDatabase.MIGRATION_19_20, AppDatabase.MIGRATION_20_21)
|
||||
.build()
|
||||
AppDatabase.MIGRATION_19_20, AppDatabase.MIGRATION_20_21, AppDatabase.MIGRATION_21_22,
|
||||
AppDatabase.MIGRATION_22_23)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesHtmlConverter(): HtmlConverter {
|
||||
return HtmlConverterImpl()
|
||||
}
|
||||
}
|
@ -6,17 +6,18 @@ import com.keylesspalace.tusky.db.AppDatabase
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.repository.TimelineRepository
|
||||
import com.keylesspalace.tusky.repository.TimelineRepositoryImpl
|
||||
import com.keylesspalace.tusky.util.HtmlConverter
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
||||
@Module
|
||||
class RepositoryModule {
|
||||
@Provides
|
||||
fun providesTimelineRepository(db: AppDatabase, mastodonApi: MastodonApi,
|
||||
accountManager: AccountManager, gson: Gson,
|
||||
htmlConverter: HtmlConverter): TimelineRepository {
|
||||
return TimelineRepositoryImpl(db.timelineDao(), mastodonApi, accountManager, gson,
|
||||
htmlConverter)
|
||||
fun providesTimelineRepository(
|
||||
db: AppDatabase,
|
||||
mastodonApi: MastodonApi,
|
||||
accountManager: AccountManager,
|
||||
gson: Gson
|
||||
): TimelineRepository {
|
||||
return TimelineRepositoryImpl(db.timelineDao(), mastodonApi, accountManager, gson)
|
||||
}
|
||||
}
|
@ -15,24 +15,16 @@
|
||||
|
||||
package com.keylesspalace.tusky.entity
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.text.Spanned
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.keylesspalace.tusky.util.HtmlUtils
|
||||
import kotlinx.android.parcel.Parceler
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.parcel.WriteWith
|
||||
import java.util.*
|
||||
import java.util.Date
|
||||
|
||||
@Parcelize
|
||||
data class Account(
|
||||
val id: String,
|
||||
@SerializedName("username") val localUsername: String,
|
||||
@SerializedName("acct", alternate = ["subject"]) val username: String,
|
||||
@SerializedName("display_name") val displayName: String?, // should never be null per Api definition, but some servers break the contract
|
||||
val note: @WriteWith<SpannedParceler>() Spanned,
|
||||
val note: Spanned,
|
||||
val url: String,
|
||||
val avatar: String,
|
||||
val header: String,
|
||||
@ -47,7 +39,7 @@ data class Account(
|
||||
val moved: Account? = null,
|
||||
@SerializedName("name") val notestockUsername: String? = null
|
||||
|
||||
) : Parcelable {
|
||||
) {
|
||||
|
||||
val name: String
|
||||
get() = notestockUsername ?: if (displayName.isNullOrEmpty()) {
|
||||
@ -87,31 +79,20 @@ data class Account(
|
||||
fun isRemote(): Boolean = this.username != this.localUsername
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class AccountSource(
|
||||
val privacy: Status.Visibility,
|
||||
val sensitive: Boolean,
|
||||
val note: String,
|
||||
val fields: List<StringField>?
|
||||
): Parcelable
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class Field (
|
||||
val name: String,
|
||||
val value: @WriteWith<SpannedParceler>() Spanned,
|
||||
val value: Spanned,
|
||||
@SerializedName("verified_at") val verifiedAt: Date?
|
||||
): Parcelable
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class StringField (
|
||||
val name: String,
|
||||
val value: String
|
||||
): Parcelable
|
||||
|
||||
object SpannedParceler : Parceler<Spanned> {
|
||||
override fun create(parcel: Parcel): Spanned = HtmlUtils.fromHtml(parcel.readString())
|
||||
|
||||
override fun Spanned.write(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(HtmlUtils.toHtml(this))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -15,23 +15,19 @@
|
||||
|
||||
package com.keylesspalace.tusky.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import android.text.Spanned
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.parcel.WriteWith
|
||||
|
||||
@Parcelize
|
||||
data class Card(
|
||||
val url: String,
|
||||
val title: @WriteWith<SpannedParceler>() Spanned,
|
||||
val description: @WriteWith<SpannedParceler>() Spanned,
|
||||
val title: Spanned,
|
||||
val description: Spanned,
|
||||
@SerializedName("author_name") val authorName: String,
|
||||
val image: String,
|
||||
val type: String,
|
||||
val width: Int,
|
||||
val height: Int
|
||||
) : Parcelable {
|
||||
) {
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return url.hashCode()
|
||||
|
@ -31,6 +31,7 @@ data class Notification(
|
||||
REBLOG("reblog"),
|
||||
FAVOURITE("favourite"),
|
||||
FOLLOW("follow"),
|
||||
FOLLOW_REQUEST("follow_request"),
|
||||
POLL("poll");
|
||||
|
||||
companion object {
|
||||
@ -43,7 +44,7 @@ data class Notification(
|
||||
}
|
||||
return UNKNOWN
|
||||
}
|
||||
val asList = listOf(MENTION, REBLOG, FAVOURITE, FOLLOW, POLL)
|
||||
val asList = listOf(MENTION, REBLOG, FAVOURITE, FOLLOW, FOLLOW_REQUEST, POLL)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
@ -9,6 +9,7 @@ data class Poll(
|
||||
val expired: Boolean,
|
||||
val multiple: Boolean,
|
||||
@SerializedName("votes_count") val votesCount: Int,
|
||||
@SerializedName("voters_count") val votersCount: Int?, // nullable for compatibility with Pleroma
|
||||
val options: List<PollOption>,
|
||||
val voted: Boolean
|
||||
) {
|
||||
@ -22,7 +23,12 @@ data class Poll(
|
||||
}
|
||||
}
|
||||
|
||||
return copy(options = newOptions, votesCount = votesCount + choices.size, voted = true)
|
||||
return copy(
|
||||
options = newOptions,
|
||||
votesCount = votesCount + choices.size,
|
||||
votersCount = votersCount?.plus(1),
|
||||
voted = true
|
||||
)
|
||||
}
|
||||
|
||||
fun toNewPoll(creationDate: Date) = NewPoll(
|
||||
|
@ -43,6 +43,7 @@ data class Status(
|
||||
val mentions: Array<Mention>,
|
||||
val application: Application?,
|
||||
var pinned: Boolean?,
|
||||
var muted: Boolean?,
|
||||
val poll: Poll?,
|
||||
val card: Card?,
|
||||
val quote: Status?
|
||||
|
@ -199,10 +199,10 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
||||
val itemCount = layoutManager.itemCount
|
||||
val lastItem = layoutManager.findLastCompletelyVisibleItemPosition()
|
||||
if (itemCount <= lastItem + 3 && fetchingStatus == FetchingStatus.NOT_FETCHING) {
|
||||
statuses.lastOrNull()?.let { last ->
|
||||
Log.d(TAG, "Requesting statuses with max_id: ${last.id}, (bottom)")
|
||||
statuses.lastOrNull()?.let { (id) ->
|
||||
Log.d(TAG, "Requesting statuses with max_id: ${id}, (bottom)")
|
||||
fetchingStatus = FetchingStatus.FETCHING_BOTTOM
|
||||
currentCall = api.accountStatuses(accountId, last.id, null, null, null, true, null)
|
||||
currentCall = api.accountStatuses(accountId, id, null, null, null, true, null)
|
||||
currentCall?.enqueue(bottomCallback)
|
||||
}
|
||||
}
|
||||
@ -254,7 +254,7 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
||||
if (view != null && activity != null) {
|
||||
val url = items[currentIndex].attachment.url
|
||||
ViewCompat.setTransitionName(view, url)
|
||||
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity!!, view, url)
|
||||
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(requireActivity(), view, url)
|
||||
startActivity(intent, options.toBundle())
|
||||
} else {
|
||||
startActivity(intent)
|
||||
|
@ -65,10 +65,13 @@ import com.keylesspalace.tusky.db.AccountManager;
|
||||
import com.keylesspalace.tusky.di.Injectable;
|
||||
import com.keylesspalace.tusky.entity.Notification;
|
||||
import com.keylesspalace.tusky.entity.Poll;
|
||||
import com.keylesspalace.tusky.entity.Relationship;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
||||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity;
|
||||
import com.keylesspalace.tusky.interfaces.ReselectableFragment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.Either;
|
||||
import com.keylesspalace.tusky.util.HttpHeaderLink;
|
||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
@ -97,6 +100,7 @@ import javax.inject.Inject;
|
||||
|
||||
import at.connyduck.sparkbutton.helpers.Utils;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
@ -114,6 +118,7 @@ public class NotificationsFragment extends SFragment implements
|
||||
SwipeRefreshLayout.OnRefreshListener,
|
||||
StatusActionListener,
|
||||
NotificationsAdapter.NotificationActionListener,
|
||||
AccountActionListener,
|
||||
Injectable, ReselectableFragment {
|
||||
private static final String TAG = "NotificationF"; // logging tag
|
||||
|
||||
@ -244,11 +249,13 @@ public class NotificationsFragment extends SFragment implements
|
||||
accountManager.getActiveAccount().getMediaPreviewEnabled(),
|
||||
preferences.getBoolean("absoluteTimeView", false),
|
||||
preferences.getBoolean("showBotOverlay", true),
|
||||
preferences.getBoolean("useBlurhash", true)
|
||||
preferences.getBoolean("useBlurhash", true),
|
||||
CardViewMode.NONE,
|
||||
preferences.getBoolean("confirmReblogs", true)
|
||||
);
|
||||
|
||||
adapter = new NotificationsAdapter(accountManager.getActiveAccount().getAccountId(),
|
||||
dataSource, statusDisplayOptions, this, this);
|
||||
dataSource, statusDisplayOptions, this, this, this);
|
||||
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
|
||||
alwaysOpenSpoiler = accountManager.getActiveAccount().getAlwaysOpenSpoiler();
|
||||
recyclerView.setAdapter(adapter);
|
||||
@ -767,6 +774,8 @@ public class NotificationsFragment extends SFragment implements
|
||||
return getString(R.string.notification_boost_name);
|
||||
case FOLLOW:
|
||||
return getString(R.string.notification_follow_name);
|
||||
case FOLLOW_REQUEST:
|
||||
return getString(R.string.notification_follow_request_name);
|
||||
case POLL:
|
||||
return getString(R.string.notification_poll_name);
|
||||
default:
|
||||
@ -819,6 +828,29 @@ public class NotificationsFragment extends SFragment implements
|
||||
super.viewAccount(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMute(boolean mute, String id, int position) {
|
||||
// No muting from notifications yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlock(boolean block, String id, int position) {
|
||||
// No blocking from notifications yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRespondToFollowRequest(boolean accept, String id, int position) {
|
||||
Single<Relationship> request = accept ?
|
||||
mastodonApi.authorizeFollowRequestObservable(id) :
|
||||
mastodonApi.rejectFollowRequestObservable(id);
|
||||
request.observeOn(AndroidSchedulers.mainThread())
|
||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||
.subscribe(
|
||||
(relationship) -> fullyRefreshWithProgressBar(true),
|
||||
(error) -> Log.e(TAG, String.format("Failed to %s account id %s", accept ? "accept" : "reject", id))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewStatusForNotificationId(String notificationId) {
|
||||
for (Either<Placeholder, Notification> either : notifications) {
|
||||
|
@ -39,6 +39,7 @@ import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.app.ActivityOptionsCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.BottomSheetActivity;
|
||||
@ -215,11 +216,8 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
|
||||
PopupMenu popup = new PopupMenu(getContext(), view);
|
||||
// Give a different menu depending on whether this is the user's own toot or not.
|
||||
if (loggedInAccountId == null || !loggedInAccountId.equals(accountId)) {
|
||||
popup.inflate(R.menu.status_more);
|
||||
Menu menu = popup.getMenu();
|
||||
menu.findItem(R.id.status_download_media).setVisible(!status.getAttachments().isEmpty());
|
||||
} else {
|
||||
boolean statusIsByCurrentUser = loggedInAccountId != null && loggedInAccountId.equals(accountId);
|
||||
if (statusIsByCurrentUser) {
|
||||
popup.inflate(R.menu.status_more_for_user);
|
||||
Menu menu = popup.getMenu();
|
||||
switch (status.getVisibility()) {
|
||||
@ -238,6 +236,10 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
popup.inflate(R.menu.status_more);
|
||||
Menu menu = popup.getMenu();
|
||||
menu.findItem(R.id.status_download_media).setVisible(!status.getAttachments().isEmpty());
|
||||
}
|
||||
|
||||
Menu menu = popup.getMenu();
|
||||
@ -261,6 +263,15 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
}
|
||||
openAsItem.setTitle(openAsTitle);
|
||||
|
||||
MenuItem muteConversationItem = menu.findItem(R.id.status_mute_conversation);
|
||||
boolean mutable = statusIsByCurrentUser || accountIsInMentions(activeAccount, status.getMentions());
|
||||
muteConversationItem.setVisible(mutable);
|
||||
if (mutable) {
|
||||
muteConversationItem.setTitle((status.getMuted() == null || !status.getMuted()) ?
|
||||
R.string.action_mute_conversation :
|
||||
R.string.action_unmute_conversation);
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener(item -> {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.status_share_content: {
|
||||
@ -304,11 +315,11 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
return true;
|
||||
}
|
||||
case R.id.status_mute: {
|
||||
timelineCases.mute(accountId);
|
||||
onMute(accountId, accountUsername);
|
||||
return true;
|
||||
}
|
||||
case R.id.status_block: {
|
||||
timelineCases.block(accountId);
|
||||
onBlock(accountId, accountUsername);
|
||||
return true;
|
||||
}
|
||||
case R.id.status_report: {
|
||||
@ -335,12 +346,52 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
timelineCases.pin(status, !status.isPinned());
|
||||
return true;
|
||||
}
|
||||
case R.id.status_mute_conversation: {
|
||||
timelineCases.muteConversation(status, status.getMuted() == null || !status.getMuted())
|
||||
.onErrorReturnItem(status)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||
.subscribe();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
popup.show();
|
||||
}
|
||||
|
||||
private void onMute(String accountId, String accountUsername) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setMessage(getString(R.string.dialog_mute_warning, accountUsername))
|
||||
.setPositiveButton(android.R.string.ok, (__, ___) -> timelineCases.mute(accountId))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onBlock(String accountId, String accountUsername) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setMessage(getString(R.string.dialog_block_warning, accountUsername))
|
||||
.setPositiveButton(android.R.string.ok, (__, ___) -> timelineCases.block(accountId))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private static boolean accountIsInMentions(AccountEntity account, Status.Mention[] mentions) {
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Status.Mention mention : mentions) {
|
||||
if (account.getUsername().equals(mention.getUsername())) {
|
||||
Uri uri = Uri.parse(mention.getUrl());
|
||||
if (uri != null && account.getDomain().equals(uri.getHost())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void viewMedia(int urlIndex, Status status, @Nullable View view) {
|
||||
final Status actionable = status.getActionableStatus();
|
||||
final Attachment active = actionable.getAttachments().get(urlIndex);
|
||||
|
@ -56,6 +56,7 @@ import com.keylesspalace.tusky.appstore.BookmarkEvent;
|
||||
import com.keylesspalace.tusky.appstore.DomainMuteEvent;
|
||||
import com.keylesspalace.tusky.appstore.EventHub;
|
||||
import com.keylesspalace.tusky.appstore.FavoriteEvent;
|
||||
import com.keylesspalace.tusky.appstore.MuteConversationEvent;
|
||||
import com.keylesspalace.tusky.appstore.MuteEvent;
|
||||
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent;
|
||||
import com.keylesspalace.tusky.appstore.QuickReplyEvent;
|
||||
@ -78,6 +79,7 @@ import com.keylesspalace.tusky.network.MastodonApi;
|
||||
import com.keylesspalace.tusky.repository.Placeholder;
|
||||
import com.keylesspalace.tusky.repository.TimelineRepository;
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.Either;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
@ -229,7 +231,7 @@ public class TimelineFragment extends SFragment implements
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Bundle arguments = Objects.requireNonNull(getArguments());
|
||||
Bundle arguments = requireArguments();
|
||||
kind = Kind.valueOf(arguments.getString(KIND_ARG));
|
||||
if (kind == Kind.TAG
|
||||
|| kind == Kind.USER
|
||||
@ -245,7 +247,11 @@ public class TimelineFragment extends SFragment implements
|
||||
accountManager.getActiveAccount().getMediaPreviewEnabled(),
|
||||
preferences.getBoolean("absoluteTimeView", false),
|
||||
preferences.getBoolean("showBotOverlay", true),
|
||||
preferences.getBoolean("useBlurhash", true)
|
||||
preferences.getBoolean("useBlurhash", true),
|
||||
preferences.getBoolean("showCardsInTimelines", false) ?
|
||||
CardViewMode.INDENTED :
|
||||
CardViewMode.NONE,
|
||||
preferences.getBoolean("confirmReblogs", true)
|
||||
);
|
||||
adapter = new TimelineAdapter(dataSource, statusDisplayOptions, this);
|
||||
|
||||
@ -568,6 +574,9 @@ public class TimelineFragment extends SFragment implements
|
||||
} else if (event instanceof BookmarkEvent) {
|
||||
BookmarkEvent bookmarkEvent = (BookmarkEvent) event;
|
||||
handleBookmarkEvent(bookmarkEvent);
|
||||
} else if (event instanceof MuteConversationEvent) {
|
||||
MuteConversationEvent muteEvent = (MuteConversationEvent) event;
|
||||
handleMuteConversationEvent(muteEvent);
|
||||
} else if (event instanceof UnfollowEvent) {
|
||||
if (kind == Kind.HOME) {
|
||||
String id = ((UnfollowEvent) event).getAccountId();
|
||||
@ -1428,6 +1437,10 @@ public class TimelineFragment extends SFragment implements
|
||||
setBookmarkForStatus(pos, status, bookmarkEvent.getBookmark());
|
||||
}
|
||||
|
||||
private void handleMuteConversationEvent(@NonNull MuteConversationEvent event) {
|
||||
fullyRefresh();
|
||||
}
|
||||
|
||||
private void handleStatusComposeEvent(@NonNull Status status) {
|
||||
switch (kind) {
|
||||
case HOME:
|
||||
|
@ -89,7 +89,7 @@ class ViewImageFragment : ViewMediaFragment() {
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
toolbar = activity!!.toolbar
|
||||
toolbar = requireActivity().toolbar
|
||||
this.transition = BehaviorSubject.create()
|
||||
return inflater.inflate(R.layout.fragment_view_image, container, false)
|
||||
}
|
||||
@ -97,7 +97,7 @@ class ViewImageFragment : ViewMediaFragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val arguments = this.arguments!!
|
||||
val arguments = this.requireArguments()
|
||||
val attachment = arguments.getParcelable<Attachment>(ARG_ATTACHMENT)
|
||||
this.shouldStartTransition = arguments.getBoolean(ARG_START_POSTPONED_TRANSITION)
|
||||
val url: String?
|
||||
|
@ -58,6 +58,7 @@ import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.entity.StatusContext;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.network.MastodonApi;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
import com.keylesspalace.tusky.util.PairedList;
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
||||
@ -131,7 +132,11 @@ public final class ViewThreadFragment extends SFragment implements
|
||||
accountManager.getActiveAccount().getMediaPreviewEnabled(),
|
||||
preferences.getBoolean("absoluteTimeView", false),
|
||||
preferences.getBoolean("showBotOverlay", true),
|
||||
preferences.getBoolean("useBlurhash", true)
|
||||
preferences.getBoolean("useBlurhash", true),
|
||||
preferences.getBoolean("showCardsInTimelines", false) ?
|
||||
CardViewMode.INDENTED :
|
||||
CardViewMode.NONE,
|
||||
preferences.getBoolean("confirmReblogs", true)
|
||||
);
|
||||
adapter = new ThreadAdapter(statusDisplayOptions, this);
|
||||
}
|
||||
|
@ -136,12 +136,12 @@ class ViewVideoFragment : ViewMediaFragment() {
|
||||
|
||||
progressBar.hide()
|
||||
mp.isLooping = true
|
||||
if (arguments!!.getBoolean(ARG_START_POSTPONED_TRANSITION)) {
|
||||
if (requireArguments().getBoolean(ARG_START_POSTPONED_TRANSITION)) {
|
||||
videoView.start()
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments!!.getBoolean(ARG_START_POSTPONED_TRANSITION)) {
|
||||
if (requireArguments().getBoolean(ARG_START_POSTPONED_TRANSITION)) {
|
||||
mediaActivity.onBringUp()
|
||||
}
|
||||
}
|
||||
@ -151,7 +151,7 @@ class ViewVideoFragment : ViewMediaFragment() {
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
toolbar = activity!!.toolbar
|
||||
toolbar = requireActivity().toolbar
|
||||
mediaActivity = activity as ViewMediaActivity
|
||||
return inflater.inflate(R.layout.fragment_view_video, container, false)
|
||||
}
|
||||
|
@ -41,42 +41,23 @@ class NotificationPreferencesFragment : PreferenceFragmentCompat(), Preference.O
|
||||
val activeAccount = accountManager.activeAccount
|
||||
|
||||
if (activeAccount != null) {
|
||||
|
||||
val notificationPref = requirePreference("notificationsEnabled") as SwitchPreferenceCompat
|
||||
notificationPref.isChecked = activeAccount.notificationsEnabled
|
||||
notificationPref.onPreferenceChangeListener = this
|
||||
|
||||
val mentionedPref = requirePreference("notificationFilterMentions") as SwitchPreferenceCompat
|
||||
mentionedPref.isChecked = activeAccount.notificationsMentioned
|
||||
mentionedPref.onPreferenceChangeListener = this
|
||||
|
||||
val followedPref = requirePreference("notificationFilterFollows") as SwitchPreferenceCompat
|
||||
followedPref.isChecked = activeAccount.notificationsFollowed
|
||||
followedPref.onPreferenceChangeListener = this
|
||||
|
||||
val boostedPref = requirePreference("notificationFilterReblogs") as SwitchPreferenceCompat
|
||||
boostedPref.isChecked = activeAccount.notificationsReblogged
|
||||
boostedPref.onPreferenceChangeListener = this
|
||||
|
||||
val favoritedPref = requirePreference("notificationFilterFavourites") as SwitchPreferenceCompat
|
||||
favoritedPref.isChecked = activeAccount.notificationsFavorited
|
||||
favoritedPref.onPreferenceChangeListener = this
|
||||
|
||||
val pollsPref = requirePreference("notificationFilterPolls") as SwitchPreferenceCompat
|
||||
pollsPref.isChecked = activeAccount.notificationsPolls
|
||||
pollsPref.onPreferenceChangeListener = this
|
||||
|
||||
val soundPref = requirePreference("notificationAlertSound") as SwitchPreferenceCompat
|
||||
soundPref.isChecked = activeAccount.notificationSound
|
||||
soundPref.onPreferenceChangeListener = this
|
||||
|
||||
val vibrationPref = requirePreference("notificationAlertVibrate") as SwitchPreferenceCompat
|
||||
vibrationPref.isChecked = activeAccount.notificationVibration
|
||||
vibrationPref.onPreferenceChangeListener = this
|
||||
|
||||
val lightPref = requirePreference("notificationAlertLight") as SwitchPreferenceCompat
|
||||
lightPref.isChecked = activeAccount.notificationLight
|
||||
lightPref.onPreferenceChangeListener = this
|
||||
for (pair in mapOf(
|
||||
"notificationsEnabled" to activeAccount.notificationsEnabled,
|
||||
"notificationFilterMentions" to activeAccount.notificationsMentioned,
|
||||
"notificationFilterFollows" to activeAccount.notificationsFollowed,
|
||||
"notificationFilterFollowRequests" to activeAccount.notificationsFollowRequested,
|
||||
"notificationFilterReblogs" to activeAccount.notificationsReblogged,
|
||||
"notificationFilterFavourites" to activeAccount.notificationsFavorited,
|
||||
"notificationFilterPolls" to activeAccount.notificationsPolls,
|
||||
"notificationAlertSound" to activeAccount.notificationSound,
|
||||
"notificationAlertVibrate" to activeAccount.notificationVibration,
|
||||
"notificationAlertLight" to activeAccount.notificationLight
|
||||
)) {
|
||||
(requirePreference(pair.key) as SwitchPreferenceCompat).apply {
|
||||
isChecked = pair.value
|
||||
onPreferenceChangeListener = this@NotificationPreferencesFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,6 +77,7 @@ class NotificationPreferencesFragment : PreferenceFragmentCompat(), Preference.O
|
||||
}
|
||||
"notificationFilterMentions" -> activeAccount.notificationsMentioned = newValue as Boolean
|
||||
"notificationFilterFollows" -> activeAccount.notificationsFollowed = newValue as Boolean
|
||||
"notificationFilterFollowRequests" -> activeAccount.notificationsFollowRequested = newValue as Boolean
|
||||
"notificationFilterReblogs" -> activeAccount.notificationsReblogged = newValue as Boolean
|
||||
"notificationFilterFavourites" -> activeAccount.notificationsFavorited = newValue as Boolean
|
||||
"notificationFilterPolls" -> activeAccount.notificationsPolls = newValue as Boolean
|
||||
|
@ -18,6 +18,8 @@ package com.keylesspalace.tusky.json;
|
||||
import android.text.Spanned;
|
||||
import android.text.SpannedString;
|
||||
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
@ -25,7 +27,6 @@ import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.keylesspalace.tusky.util.HtmlUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@ -35,7 +36,9 @@ public class SpannedTypeAdapter implements JsonDeserializer<Spanned>, JsonSerial
|
||||
throws JsonParseException {
|
||||
String string = json.getAsString();
|
||||
if (string != null) {
|
||||
return HtmlUtils.fromHtml(string);
|
||||
/* Html.fromHtml returns trailing whitespace if the html ends in a </p> tag, which
|
||||
* all status contents do, so it should be trimmed. */
|
||||
return (Spanned)trimTrailingWhitespace(HtmlCompat.fromHtml(string, HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||
} else {
|
||||
return new SpannedString("");
|
||||
}
|
||||
@ -43,6 +46,14 @@ public class SpannedTypeAdapter implements JsonDeserializer<Spanned>, JsonSerial
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Spanned src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(HtmlUtils.toHtml(src));
|
||||
return new JsonPrimitive(HtmlCompat.toHtml(src, HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL));
|
||||
}
|
||||
|
||||
private static CharSequence trimTrailingWhitespace(CharSequence s) {
|
||||
int i = s.length();
|
||||
do {
|
||||
i--;
|
||||
} while (i >= 0 && Character.isWhitespace(s.charAt(i)));
|
||||
return s.subSequence(0, i + 1);
|
||||
}
|
||||
}
|
||||
|
@ -200,6 +200,16 @@ interface MastodonApi {
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/mute")
|
||||
fun muteConversation(
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@POST("api/v1/statuses/{id}/unmute")
|
||||
fun unmuteConversation(
|
||||
@Path("id") statusId: String
|
||||
): Single<Status>
|
||||
|
||||
@GET("api/v1/scheduled_statuses")
|
||||
fun scheduledStatuses(
|
||||
@Query("limit") limit: Int? = null,
|
||||
@ -383,6 +393,16 @@ interface MastodonApi {
|
||||
@Path("id") accountId: String
|
||||
): Call<Relationship>
|
||||
|
||||
@POST("api/v1/follow_requests/{id}/authorize")
|
||||
fun authorizeFollowRequestObservable(
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@POST("api/v1/follow_requests/{id}/reject")
|
||||
fun rejectFollowRequestObservable(
|
||||
@Path("id") accountId: String
|
||||
): Single<Relationship>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/apps")
|
||||
fun authenticateApp(
|
||||
|
@ -41,7 +41,7 @@ interface TimelineCases {
|
||||
fun delete(id: String): Single<DeletedStatus>
|
||||
fun pin(status: Status, pin: Boolean)
|
||||
fun voteInPoll(status: Status, choices: List<Int>): Single<Poll>
|
||||
|
||||
fun muteConversation(status: Status, mute: Boolean): Single<Status>
|
||||
}
|
||||
|
||||
class TimelineCasesImpl(
|
||||
@ -94,6 +94,19 @@ class TimelineCasesImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun muteConversation(status: Status, mute: Boolean): Single<Status> {
|
||||
val id = status.actionableId
|
||||
|
||||
val call = if (mute) {
|
||||
mastodonApi.muteConversation(id)
|
||||
} else {
|
||||
mastodonApi.unmuteConversation(id)
|
||||
}
|
||||
return call.doAfterSuccess {
|
||||
eventHub.dispatch(MuteConversationEvent(status.id, mute))
|
||||
}
|
||||
}
|
||||
|
||||
override fun mute(id: String) {
|
||||
val call = mastodonApi.muteAccount(id)
|
||||
call.enqueue(object : Callback<Relationship> {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.keylesspalace.tusky.repository
|
||||
|
||||
import android.text.SpannedString
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.text.toHtml
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.keylesspalace.tusky.db.*
|
||||
@ -9,7 +11,6 @@ import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.DISK
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.NETWORK
|
||||
import com.keylesspalace.tusky.util.Either
|
||||
import com.keylesspalace.tusky.util.HtmlConverter
|
||||
import com.keylesspalace.tusky.util.dec
|
||||
import com.keylesspalace.tusky.util.inc
|
||||
import io.reactivex.Single
|
||||
@ -41,8 +42,7 @@ class TimelineRepositoryImpl(
|
||||
private val timelineDao: TimelineDao,
|
||||
private val mastodonApi: MastodonApi,
|
||||
private val accountManager: AccountManager,
|
||||
private val gson: Gson,
|
||||
private val htmlConverter: HtmlConverter
|
||||
private val gson: Gson
|
||||
) : TimelineRepository {
|
||||
|
||||
init {
|
||||
@ -67,7 +67,7 @@ class TimelineRepositoryImpl(
|
||||
val accountId = acc.id
|
||||
|
||||
timelineDao.insertInTransaction(
|
||||
status.toEntity(accountId, htmlConverter, gson),
|
||||
status.toEntity(accountId, gson),
|
||||
status.account.toEntity(accountId, gson),
|
||||
status.reblog?.account?.toEntity(accountId, gson)
|
||||
)
|
||||
@ -162,7 +162,7 @@ class TimelineRepositoryImpl(
|
||||
|
||||
for (status in statuses) {
|
||||
timelineDao.insertInTransaction(
|
||||
status.toEntity(accountId, htmlConverter, gson),
|
||||
status.toEntity(accountId, gson),
|
||||
status.account.toEntity(accountId, gson),
|
||||
status.reblog?.account?.toEntity(accountId, gson)
|
||||
)
|
||||
@ -226,7 +226,7 @@ class TimelineRepositoryImpl(
|
||||
inReplyToId = status.inReplyToId,
|
||||
inReplyToAccountId = status.inReplyToAccountId,
|
||||
reblog = null,
|
||||
content = status.content?.let(htmlConverter::fromHtml) ?: SpannedString(""),
|
||||
content = status.content?.parseAsHtml() ?: SpannedString(""),
|
||||
createdAt = Date(status.createdAt),
|
||||
emojis = emojis,
|
||||
reblogsCount = status.reblogsCount,
|
||||
@ -241,6 +241,7 @@ class TimelineRepositoryImpl(
|
||||
mentions = mentions,
|
||||
application = application,
|
||||
pinned = false,
|
||||
muted = status.muted,
|
||||
poll = poll,
|
||||
card = null,
|
||||
quote = null
|
||||
@ -269,6 +270,7 @@ class TimelineRepositoryImpl(
|
||||
mentions = arrayOf(),
|
||||
application = null,
|
||||
pinned = false,
|
||||
muted = status.muted,
|
||||
poll = null,
|
||||
card = null,
|
||||
quote = null
|
||||
@ -281,7 +283,7 @@ class TimelineRepositoryImpl(
|
||||
inReplyToId = status.inReplyToId,
|
||||
inReplyToAccountId = status.inReplyToAccountId,
|
||||
reblog = null,
|
||||
content = status.content?.let(htmlConverter::fromHtml) ?: SpannedString(""),
|
||||
content = status.content?.parseAsHtml() ?: SpannedString(""),
|
||||
createdAt = Date(status.createdAt),
|
||||
emojis = emojis,
|
||||
reblogsCount = status.reblogsCount,
|
||||
@ -296,6 +298,7 @@ class TimelineRepositoryImpl(
|
||||
mentions = mentions,
|
||||
application = application,
|
||||
pinned = false,
|
||||
muted = status.muted,
|
||||
poll = poll,
|
||||
card = null,
|
||||
quote = null
|
||||
@ -368,12 +371,12 @@ fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity {
|
||||
application = null,
|
||||
reblogServerId = null,
|
||||
reblogAccountId = null,
|
||||
poll = null
|
||||
poll = null,
|
||||
muted = false
|
||||
)
|
||||
}
|
||||
|
||||
fun Status.toEntity(timelineUserId: Long,
|
||||
htmlConverter: HtmlConverter,
|
||||
gson: Gson): TimelineStatusEntity {
|
||||
val actionable = actionableStatus
|
||||
return TimelineStatusEntity(
|
||||
@ -383,7 +386,7 @@ fun Status.toEntity(timelineUserId: Long,
|
||||
authorServerId = actionable.account.id,
|
||||
inReplyToId = actionable.inReplyToId,
|
||||
inReplyToAccountId = actionable.inReplyToAccountId,
|
||||
content = htmlConverter.toHtml(actionable.content),
|
||||
content = actionable.content.toHtml(),
|
||||
createdAt = actionable.createdAt.time,
|
||||
emojis = actionable.emojis.let(gson::toJson),
|
||||
reblogsCount = actionable.reblogsCount,
|
||||
@ -396,10 +399,11 @@ fun Status.toEntity(timelineUserId: Long,
|
||||
visibility = actionable.visibility,
|
||||
attachments = actionable.attachments.let(gson::toJson),
|
||||
mentions = actionable.mentions.let(gson::toJson),
|
||||
application = actionable.let(gson::toJson),
|
||||
application = actionable.application.let(gson::toJson),
|
||||
reblogServerId = reblog?.id,
|
||||
reblogAccountId = reblog?.let { this.account.id },
|
||||
poll = actionable.poll.let(gson::toJson)
|
||||
poll = actionable.poll.let(gson::toJson),
|
||||
muted = actionable.muted
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
package com.keylesspalace.tusky.util
|
||||
|
||||
enum class CardViewMode {
|
||||
NONE,
|
||||
FULL_WIDTH,
|
||||
INDENTED
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package com.keylesspalace.tusky.util
|
||||
|
||||
import android.text.Spanned
|
||||
|
||||
/**
|
||||
* Abstracting away Android-specific things.
|
||||
*/
|
||||
interface HtmlConverter {
|
||||
fun fromHtml(html: String): Spanned
|
||||
|
||||
fun toHtml(text: Spanned): String
|
||||
}
|
||||
|
||||
internal class HtmlConverterImpl : HtmlConverter {
|
||||
override fun fromHtml(html: String): Spanned {
|
||||
return HtmlUtils.fromHtml(html)
|
||||
}
|
||||
|
||||
override fun toHtml(text: Spanned): String {
|
||||
return HtmlUtils.toHtml(text)
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* 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.util;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
|
||||
public class HtmlUtils {
|
||||
private static CharSequence trimTrailingWhitespace(CharSequence s) {
|
||||
int i = s.length();
|
||||
do {
|
||||
i--;
|
||||
} while (i >= 0 && Character.isWhitespace(s.charAt(i)));
|
||||
return s.subSequence(0, i + 1);
|
||||
}
|
||||
|
||||
public static Spanned fromHtml(String html) {
|
||||
Spanned result;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
|
||||
} else {
|
||||
result = Html.fromHtml(html);
|
||||
}
|
||||
/* Html.fromHtml returns trailing whitespace if the html ends in a </p> tag, which
|
||||
* all status contents do, so it should be trimmed. */
|
||||
return (Spanned) trimTrailingWhitespace(result);
|
||||
}
|
||||
|
||||
public static String toHtml(Spanned text) {
|
||||
String result;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
result = Html.toHtml(text, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
|
||||
} else {
|
||||
result = Html.toHtml(text);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -82,6 +82,8 @@ class ListStatusAccessibilityDelegate(
|
||||
}
|
||||
if (status.reblogsCount > 0) info.addAction(openRebloggedByAction)
|
||||
if (status.favouritesCount > 0) info.addAction(openFavsAction)
|
||||
|
||||
info.addAction(moreAction)
|
||||
}
|
||||
|
||||
}
|
||||
@ -150,6 +152,9 @@ class ListStatusAccessibilityDelegate(
|
||||
interrupt()
|
||||
statusActionListener.onShowFavs(pos)
|
||||
}
|
||||
R.id.action_more -> {
|
||||
statusActionListener.onMore(host, pos)
|
||||
}
|
||||
else -> return super.performAccessibilityAction(host, action, args)
|
||||
}
|
||||
return true
|
||||
@ -311,5 +316,10 @@ class ListStatusAccessibilityDelegate(
|
||||
R.id.action_open_faved_by,
|
||||
context.getString(R.string.action_open_faved_by))
|
||||
|
||||
private val moreAction = AccessibilityActionCompat(
|
||||
R.id.action_more,
|
||||
context.getString(R.string.action_more)
|
||||
)
|
||||
|
||||
private data class LinkSpanInfo(val text: String, val link: String)
|
||||
}
|
@ -113,6 +113,7 @@ public class NotificationHelper {
|
||||
**/
|
||||
public static final String CHANNEL_MENTION = "CHANNEL_MENTION";
|
||||
public static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW";
|
||||
public static final String CHANNEL_FOLLOW_REQUEST = "CHANNEL_FOLLOW_REQUEST";
|
||||
public static final String CHANNEL_BOOST = "CHANNEL_BOOST";
|
||||
public static final String CHANNEL_FAVOURITE = "CHANNEL_FAVOURITE";
|
||||
public static final String CHANNEL_POLL = "CHANNEL_POLL";
|
||||
@ -348,6 +349,7 @@ public class NotificationHelper {
|
||||
String[] channelIds = new String[]{
|
||||
CHANNEL_MENTION + account.getIdentifier(),
|
||||
CHANNEL_FOLLOW + account.getIdentifier(),
|
||||
CHANNEL_FOLLOW_REQUEST + account.getIdentifier(),
|
||||
CHANNEL_BOOST + account.getIdentifier(),
|
||||
CHANNEL_FAVOURITE + account.getIdentifier(),
|
||||
CHANNEL_POLL + account.getIdentifier(),
|
||||
@ -355,6 +357,7 @@ public class NotificationHelper {
|
||||
int[] channelNames = {
|
||||
R.string.notification_mention_name,
|
||||
R.string.notification_follow_name,
|
||||
R.string.notification_follow_request_name,
|
||||
R.string.notification_boost_name,
|
||||
R.string.notification_favourite_name,
|
||||
R.string.notification_poll_name
|
||||
@ -362,12 +365,13 @@ public class NotificationHelper {
|
||||
int[] channelDescriptions = {
|
||||
R.string.notification_mention_descriptions,
|
||||
R.string.notification_follow_description,
|
||||
R.string.notification_follow_request_description,
|
||||
R.string.notification_boost_description,
|
||||
R.string.notification_favourite_description,
|
||||
R.string.notification_poll_description
|
||||
};
|
||||
|
||||
List<NotificationChannel> channels = new ArrayList<>(5);
|
||||
List<NotificationChannel> channels = new ArrayList<>(6);
|
||||
|
||||
NotificationChannelGroup channelGroup = new NotificationChannelGroup(account.getIdentifier(), account.getFullName());
|
||||
|
||||
@ -508,6 +512,8 @@ public class NotificationHelper {
|
||||
return account.getNotificationsMentioned();
|
||||
case FOLLOW:
|
||||
return account.getNotificationsFollowed();
|
||||
case FOLLOW_REQUEST:
|
||||
return account.getNotificationsFollowRequested();
|
||||
case REBLOG:
|
||||
return account.getNotificationsReblogged();
|
||||
case FAVOURITE:
|
||||
@ -525,6 +531,8 @@ public class NotificationHelper {
|
||||
return CHANNEL_MENTION + account.getIdentifier();
|
||||
case FOLLOW:
|
||||
return CHANNEL_FOLLOW + account.getIdentifier();
|
||||
case FOLLOW_REQUEST:
|
||||
return CHANNEL_FOLLOW_REQUEST + account.getIdentifier();
|
||||
case REBLOG:
|
||||
return CHANNEL_BOOST + account.getIdentifier();
|
||||
case FAVOURITE:
|
||||
@ -594,6 +602,9 @@ public class NotificationHelper {
|
||||
case FOLLOW:
|
||||
return String.format(context.getString(R.string.notification_follow_format),
|
||||
accountName);
|
||||
case FOLLOW_REQUEST:
|
||||
return String.format(context.getString(R.string.notification_follow_request_format),
|
||||
accountName);
|
||||
case FAVOURITE:
|
||||
return String.format(context.getString(R.string.notification_favourite_format),
|
||||
accountName);
|
||||
@ -613,6 +624,7 @@ public class NotificationHelper {
|
||||
private static String bodyForType(Notification notification, Context context) {
|
||||
switch (notification.getType()) {
|
||||
case FOLLOW:
|
||||
case FOLLOW_REQUEST:
|
||||
return "@" + notification.getAccount().getUsername();
|
||||
case MENTION:
|
||||
case FAVOURITE:
|
||||
@ -631,7 +643,7 @@ public class NotificationHelper {
|
||||
Poll poll = notification.getStatus().getPoll();
|
||||
for(PollOption option: poll.getOptions()) {
|
||||
builder.append(buildDescription(option.getTitle(),
|
||||
PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotesCount()),
|
||||
PollViewDataKt.calculatePercent(option.getVotesCount(), poll.getVotersCount(), poll.getVotesCount()),
|
||||
context));
|
||||
builder.append('\n');
|
||||
}
|
||||
|
@ -10,5 +10,9 @@ data class StatusDisplayOptions(
|
||||
@get:JvmName("showBotOverlay")
|
||||
val showBotOverlay: Boolean,
|
||||
@get:JvmName("useBlurhash")
|
||||
val useBlurhash: Boolean
|
||||
val useBlurhash: Boolean,
|
||||
@get:JvmName("cardViewMode")
|
||||
val cardViewMode: CardViewMode,
|
||||
@get:JvmName("confirmReblogs")
|
||||
val confirmReblogs: Boolean
|
||||
)
|
@ -24,7 +24,6 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.bumptech.glide.Glide
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
@ -172,15 +171,12 @@ class StatusViewHelper(private val itemView: View) {
|
||||
sensitiveMediaWarning.visibility = View.GONE
|
||||
sensitiveMediaShow.visibility = View.GONE
|
||||
} else {
|
||||
|
||||
val hiddenContentText: String = if (sensitive) {
|
||||
sensitiveMediaWarning.text = if (sensitive) {
|
||||
context.getString(R.string.status_sensitive_media_title)
|
||||
} else {
|
||||
context.getString(R.string.status_media_hidden_title)
|
||||
}
|
||||
|
||||
sensitiveMediaWarning.text = HtmlUtils.fromHtml(hiddenContentText)
|
||||
|
||||
sensitiveMediaWarning.visibility = if (showingContent) View.GONE else View.VISIBLE
|
||||
sensitiveMediaShow.visibility = if (showingContent) View.VISIBLE else View.GONE
|
||||
sensitiveMediaShow.setOnClickListener { v ->
|
||||
@ -275,17 +271,22 @@ class StatusViewHelper(private val itemView: View) {
|
||||
|
||||
private fun getPollInfoText(timestamp: Long, poll: PollViewData, pollDescription: TextView, useAbsoluteTime: Boolean): CharSequence {
|
||||
val context = pollDescription.context
|
||||
val votes = NumberFormat.getNumberInstance().format(poll.votesCount.toLong())
|
||||
val votesText = context.resources.getQuantityString(R.plurals.poll_info_votes, poll.votesCount, votes)
|
||||
val pollDurationInfo: CharSequence
|
||||
if (poll.expired) {
|
||||
pollDurationInfo = context.getString(R.string.poll_info_closed)
|
||||
|
||||
val votesText = if(poll.votersCount == null) {
|
||||
val votes = NumberFormat.getNumberInstance().format(poll.votesCount.toLong())
|
||||
context.resources.getQuantityString(R.plurals.poll_info_votes, poll.votesCount, votes)
|
||||
} else {
|
||||
val votes = NumberFormat.getNumberInstance().format(poll.votersCount.toLong())
|
||||
context.resources.getQuantityString(R.plurals.poll_info_people, poll.votersCount, votes)
|
||||
}
|
||||
val pollDurationInfo = if (poll.expired) {
|
||||
context.getString(R.string.poll_info_closed)
|
||||
} else {
|
||||
if (useAbsoluteTime) {
|
||||
pollDurationInfo = context.getString(R.string.poll_info_time_absolute, getAbsoluteTime(poll.expiresAt))
|
||||
context.getString(R.string.poll_info_time_absolute, getAbsoluteTime(poll.expiresAt))
|
||||
} else {
|
||||
val pollDuration = TimestampUtils.formatPollDuration(context, poll.expiresAt!!.time, timestamp)
|
||||
pollDurationInfo = context.getString(R.string.poll_info_time_relative, pollDuration)
|
||||
context.getString(R.string.poll_info_time_relative, pollDuration)
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +299,7 @@ class StatusViewHelper(private val itemView: View) {
|
||||
|
||||
for (i in 0 until Status.MAX_POLL_OPTIONS) {
|
||||
if (i < options.size) {
|
||||
val percent = calculatePercent(options[i].votesCount, poll.votesCount)
|
||||
val percent = calculatePercent(options[i].votesCount, poll.votersCount, poll.votesCount)
|
||||
|
||||
val pollOptionText = buildDescription(options[i].title, percent, pollResults[i].context)
|
||||
pollResults[i].text = CustomEmojiHelper.emojifyText(pollOptionText, emojis, pollResults[i])
|
||||
|
@ -18,10 +18,10 @@ package com.keylesspalace.tusky.viewdata
|
||||
import android.content.Context
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import androidx.core.text.parseAsHtml
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.PollOption
|
||||
import com.keylesspalace.tusky.util.HtmlUtils
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@ -31,6 +31,7 @@ data class PollViewData(
|
||||
val expired: Boolean,
|
||||
val multiple: Boolean,
|
||||
val votesCount: Int,
|
||||
val votersCount: Int?,
|
||||
val options: List<PollOptionViewData>,
|
||||
var voted: Boolean
|
||||
)
|
||||
@ -41,16 +42,17 @@ data class PollOptionViewData(
|
||||
var selected: Boolean
|
||||
)
|
||||
|
||||
fun calculatePercent(fraction: Int, total: Int): Int {
|
||||
fun calculatePercent(fraction: Int, totalVoters: Int?, totalVotes: Int): Int {
|
||||
return if (fraction == 0) {
|
||||
0
|
||||
} else {
|
||||
val total = totalVoters ?: totalVotes
|
||||
(fraction / total.toDouble() * 100).roundToInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun buildDescription(title: String, percent: Int, context: Context): Spanned {
|
||||
return SpannableStringBuilder(HtmlUtils.fromHtml(context.getString(R.string.poll_percent_format, percent)))
|
||||
return SpannableStringBuilder(context.getString(R.string.poll_percent_format, percent).parseAsHtml())
|
||||
.append(" ")
|
||||
.append(title)
|
||||
}
|
||||
@ -58,20 +60,21 @@ fun buildDescription(title: String, percent: Int, context: Context): Spanned {
|
||||
fun Poll?.toViewData(): PollViewData? {
|
||||
if (this == null) return null
|
||||
return PollViewData(
|
||||
id,
|
||||
expiresAt,
|
||||
expired,
|
||||
multiple,
|
||||
votesCount,
|
||||
options.map { it.toViewData() },
|
||||
voted
|
||||
id = id,
|
||||
expiresAt = expiresAt,
|
||||
expired = expired,
|
||||
multiple = multiple,
|
||||
votesCount = votesCount,
|
||||
votersCount = votersCount,
|
||||
options = options.map { it.toViewData() },
|
||||
voted = voted
|
||||
)
|
||||
}
|
||||
|
||||
fun PollOption.toViewData(): PollOptionViewData {
|
||||
return PollOptionViewData(
|
||||
title,
|
||||
votesCount,
|
||||
false
|
||||
title = title,
|
||||
votesCount = votesCount,
|
||||
selected = false
|
||||
)
|
||||
}
|
@ -58,6 +58,7 @@ public abstract class StatusViewData {
|
||||
final boolean reblogged;
|
||||
final boolean favourited;
|
||||
final boolean bookmarked;
|
||||
private final boolean muted;
|
||||
@Nullable
|
||||
private final String spoilerText;
|
||||
private final Status.Visibility visibility;
|
||||
@ -96,7 +97,7 @@ public abstract class StatusViewData {
|
||||
private final Status quote;
|
||||
private final boolean isNotestock;
|
||||
|
||||
public Concrete(String id, Spanned content, boolean reblogged, boolean favourited, boolean bookmarked,
|
||||
public Concrete(String id, Spanned content, boolean reblogged, boolean favourited, boolean bookmarked, boolean muted,
|
||||
@Nullable String spoilerText, Status.Visibility visibility, List<Attachment> attachments,
|
||||
@Nullable String rebloggedByUsername, @Nullable String rebloggedAvatar, boolean sensitive, boolean isExpanded,
|
||||
boolean isShowingContent, String userFullName, String nickname, String avatar,
|
||||
@ -119,6 +120,7 @@ public abstract class StatusViewData {
|
||||
this.reblogged = reblogged;
|
||||
this.favourited = favourited;
|
||||
this.bookmarked = bookmarked;
|
||||
this.muted = muted;
|
||||
this.visibility = visibility;
|
||||
this.attachments = attachments;
|
||||
this.rebloggedByUsername = rebloggedByUsername;
|
||||
@ -167,6 +169,10 @@ public abstract class StatusViewData {
|
||||
return bookmarked;
|
||||
}
|
||||
|
||||
public boolean isMuted() {
|
||||
return muted;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSpoilerText() {
|
||||
return spoilerText;
|
||||
@ -419,6 +425,7 @@ public abstract class StatusViewData {
|
||||
private boolean reblogged;
|
||||
private boolean favourited;
|
||||
private boolean bookmarked;
|
||||
private boolean muted;
|
||||
private String spoilerText;
|
||||
private Status.Visibility visibility;
|
||||
private List<Attachment> attachments;
|
||||
@ -457,6 +464,7 @@ public abstract class StatusViewData {
|
||||
reblogged = viewData.reblogged;
|
||||
favourited = viewData.favourited;
|
||||
bookmarked = viewData.bookmarked;
|
||||
muted = viewData.muted;
|
||||
spoilerText = viewData.spoilerText;
|
||||
visibility = viewData.visibility;
|
||||
attachments = viewData.attachments == null ? null : new ArrayList<>(viewData.attachments);
|
||||
@ -512,6 +520,11 @@ public abstract class StatusViewData {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMuted(boolean muted) {
|
||||
this.muted = muted;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSpoilerText(String spoilerText) {
|
||||
this.spoilerText = spoilerText;
|
||||
return this;
|
||||
@ -675,7 +688,7 @@ public abstract class StatusViewData {
|
||||
if (this.accountEmojis == null) accountEmojis = Collections.emptyList();
|
||||
if (this.createdAt == null) createdAt = new Date();
|
||||
|
||||
return new StatusViewData.Concrete(id, content, reblogged, favourited, bookmarked, spoilerText,
|
||||
return new StatusViewData.Concrete(id, content, reblogged, favourited, bookmarked, muted, spoilerText,
|
||||
visibility, attachments, rebloggedByUsername, rebloggedAvatar, isSensitive, isExpanded,
|
||||
isShowingContent, userFullName, nickname, avatar, createdAt, reblogsCount,
|
||||
favouritesCount, inReplyToId, mentions, senderId, rebloggingEnabled, application,
|
||||
|
@ -255,10 +255,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorSurface"
|
||||
android:elevation="12dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="52dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingBottom="60dp"
|
||||
app:behavior_hideable="true"
|
||||
app:behavior_peekHeight="0dp"
|
||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
|
||||
|
96
app/src/main/res/layout/item_follow_request_notification.xml
Normal file
96
app/src/main/res/layout/item_follow_request_notification.xml
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/notificationTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:drawableStart="@drawable/ic_person_add_24dp"
|
||||
android:drawablePadding="10dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="28dp"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Someone requested to follow you" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginTop="10dp"
|
||||
android:contentDescription="@string/action_view_profile"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/notificationTextView" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/displayNameTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="14dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="?attr/status_text_large"
|
||||
android:textStyle="normal|bold"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/notificationTextView"
|
||||
tools:text="Display name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/usernameTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="14dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="?attr/status_text_medium"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/displayNameTextView"
|
||||
tools:text="\@username" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/acceptButton"
|
||||
style="@style/TuskyImageButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="14dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/action_accept"
|
||||
android:padding="4dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/rejectButton"
|
||||
app:layout_constraintTop_toBottomOf="@id/notificationTextView"
|
||||
app:srcCompat="@drawable/ic_check_24dp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/rejectButton"
|
||||
style="@style/TuskyImageButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="14dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/action_reject"
|
||||
android:padding="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/notificationTextView"
|
||||
app:srcCompat="@drawable/ic_reject_24dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -158,6 +158,73 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/status_content_warning_button"
|
||||
tools:text="This is a status" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/status_card_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/card_frame"
|
||||
android:clipChildren="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:minHeight="80dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/status_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/card_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
android:layout_margin="1dp"
|
||||
android:background="?attr/colorBackgroundAccent"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/card_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:paddingBottom="6dp">
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/card_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:lines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="?attr/status_text_medium" />
|
||||
|
||||
<androidx.emoji.widget.EmojiTextView
|
||||
android:id="@+id/card_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:lineSpacingMultiplier="1.1"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="?attr/status_text_medium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/card_link"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
android:textSize="?attr/status_text_medium" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_toggle_content"
|
||||
style="@style/TuskyButton.Outlined"
|
||||
@ -176,7 +243,7 @@
|
||||
android:textSize="?attr/status_text_medium"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_card_view"
|
||||
tools:text="@string/status_content_show_less"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
@ -143,7 +143,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/status_content" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/card_view"
|
||||
android:id="@+id/status_card_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
@ -216,7 +216,7 @@
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@drawable/media_preview_outline"
|
||||
android:importantForAccessibility="noHideDescendants"
|
||||
app:layout_constraintTop_toBottomOf="@id/card_view">
|
||||
app:layout_constraintTop_toBottomOf="@id/status_card_view">
|
||||
|
||||
<com.keylesspalace.tusky.view.MediaPreviewImageView
|
||||
android:id="@+id/status_media_preview_0"
|
||||
|
@ -1,55 +1,50 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:parentTag="android.widget.LinearLayout">
|
||||
tools:layout_height="wrap_content"
|
||||
tools:layout_width="match_parent"
|
||||
tools:parentTag="RadioGroup">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/visibilityRadioGroup"
|
||||
<RadioButton
|
||||
android:id="@+id/publicRadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_weight="1"
|
||||
android:button="@drawable/ic_public_24dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:text="@string/visibility_public"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/unlistedRadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/compose_options_margin"
|
||||
android:layout_marginLeft="@dimen/compose_options_margin"
|
||||
android:layout_marginRight="@dimen/compose_options_margin"
|
||||
android:layout_marginTop="4dp"
|
||||
android:orientation="vertical">
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_weight="1"
|
||||
android:button="@drawable/ic_lock_open_24dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:text="@string/visibility_unlisted"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/publicRadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingStart="10dp"
|
||||
android:text="@string/visibility_public"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/unlistedRadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingStart="10dp"
|
||||
android:text="@string/visibility_unlisted"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/privateRadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingStart="10dp"
|
||||
android:text="@string/visibility_private"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
<RadioButton
|
||||
android:id="@+id/privateRadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_weight="1"
|
||||
android:button="@drawable/ic_lock_outline_24dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:text="@string/visibility_private"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/unleakableRadioButton"
|
||||
@ -58,8 +53,9 @@
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="0dp"
|
||||
android:button="@drawable/ic_reblog_unleakable_24dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:text="@string/visibility_unleakable"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color"
|
||||
@ -71,12 +67,11 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="0dp"
|
||||
android:button="@drawable/ic_email_24dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:text="@string/visibility_direct"
|
||||
android:textColor="?android:textColorTertiary"
|
||||
app:buttonTint="@color/compound_button_color" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</merge>
|
@ -21,6 +21,9 @@
|
||||
<item
|
||||
android:id="@+id/status_download_media"
|
||||
android:title="@string/download_media" />
|
||||
<item
|
||||
android:id="@+id/status_mute_conversation"
|
||||
android:title="@string/action_mute_conversation" />
|
||||
<item
|
||||
android:id="@+id/status_mute"
|
||||
android:title="@string/action_mute" />
|
||||
|
@ -26,6 +26,9 @@
|
||||
android:id="@+id/status_unreblog_private"
|
||||
android:title="@string/unreblog_private"
|
||||
android:visible="false" />
|
||||
<item
|
||||
android:id="@+id/status_mute_conversation"
|
||||
android:title="@string/action_mute_conversation" />
|
||||
<item
|
||||
android:id="@+id/status_delete"
|
||||
android:title="@string/action_delete" />
|
||||
|
@ -2,82 +2,82 @@
|
||||
<resources>
|
||||
<string name="error_generic">وقع هناك خطأ.</string>
|
||||
<string name="error_network">حدث خطأ في الشبكة! يرجى التحقق من اتصالك ثم أعد المحاولة!</string>
|
||||
<string name="error_empty">لا يجب أن يترك فارغا.</string>
|
||||
<string name="error_invalid_domain">اسم النطاق غير صالح</string>
|
||||
<string name="error_empty">لا يجب أن يترك هذا الحقل فارغا.</string>
|
||||
<string name="error_invalid_domain">اسم النطاق الذي قمتَ بإدخاله غير صالح</string>
|
||||
<string name="error_failed_app_registration">اخفقت المصادقة مع مثيل الخادم هذا.</string>
|
||||
<string name="error_no_web_browser_found">تعذر العثور على متصفح ويب قابل للإستعمال.</string>
|
||||
<string name="error_no_web_browser_found">تعذر العثور على متصفح ويب صالح للإستعمال.</string>
|
||||
<string name="error_authorization_unknown">لقد وقع هناك خطأ مجهول في التصريح.</string>
|
||||
<string name="error_authorization_denied">تم رفض التصريح.</string>
|
||||
<string name="error_retrieving_oauth_token">فشل الحصول على رمز الدخول.</string>
|
||||
<string name="error_compose_character_limit">المنشور طويل جدا !</string>
|
||||
<string name="error_image_upload_size">يجب أن يكون حجم الملف أقل من 4 ميغابايت.</string>
|
||||
<string name="error_retrieving_oauth_token">فشل الحصول على رمز الولوج.</string>
|
||||
<string name="error_compose_character_limit">إنّ المنشور طويل جدا!</string>
|
||||
<string name="error_image_upload_size">يجب أن يكون حجم الملف أقل من 8 ميغابايت.</string>
|
||||
<string name="error_video_upload_size">يجب أن يكون حجم ملفات الفيديو أقل من 40 ميغا بايت.</string>
|
||||
<string name="error_media_upload_type">لا يمكن رفع هذا النوع من الملفات.</string>
|
||||
<string name="error_media_upload_type">لا يمكن تحميل هذا النوع من الملفات.</string>
|
||||
<string name="error_media_upload_opening">تعذر فتح ذاك الملف.</string>
|
||||
<string name="error_media_upload_permission">التصريح لازم لقراءة الوسائط.</string>
|
||||
<string name="error_media_download_permission">التصريح لازم للإحتفاظ بالوسائط.</string>
|
||||
<string name="error_media_upload_image_or_video">لا يمكنك إرفاق كلا من الصور و الفيديوهات في نفس المنشور.</string>
|
||||
<string name="error_media_upload_image_or_video">لا يمكنك إرفاق كلا من الصور والفيديوهات في نفس المنشور في آن واحد.</string>
|
||||
<string name="error_media_upload_sending">اخفقت عملية الرفع.</string>
|
||||
<string name="error_sender_account_gone">خطأ عند إرسال التبويق.</string>
|
||||
<string name="title_home">الرئيسية</string>
|
||||
<string name="title_home">الرئيسي</string>
|
||||
<string name="title_notifications">الاشعارات</string>
|
||||
<string name="title_public_local">المحلية</string>
|
||||
<string name="title_public_federated">الفدرالية</string>
|
||||
<string name="title_public_local">المحلي</string>
|
||||
<string name="title_public_federated">الفدرالي</string>
|
||||
<string name="title_direct_messages">الرسائل المباشرة</string>
|
||||
<string name="title_tab_preferences">الألسنة</string>
|
||||
<string name="title_view_thread">تبويق</string>
|
||||
<string name="title_statuses">المشاركات</string>
|
||||
<string name="title_statuses_with_replies">يحتوي على ردود</string>
|
||||
<string name="title_statuses_pinned">مدبّس</string>
|
||||
<string name="title_statuses">المنشورات</string>
|
||||
<string name="title_statuses_with_replies">التبويقات والردود</string>
|
||||
<string name="title_statuses_pinned">المدبّسة</string>
|
||||
<string name="title_follows">المتابَعون</string>
|
||||
<string name="title_followers">المتابِعون</string>
|
||||
<string name="title_favourites">المفضلة</string>
|
||||
<string name="title_mutes">الحسابات المكتومة</string>
|
||||
<string name="title_blocks">الحسابات المحظورة</string>
|
||||
<string name="title_follow_requests">طلبات المتابعة</string>
|
||||
<string name="title_edit_profile">عدل ملفك الشخصي</string>
|
||||
<string name="title_edit_profile">عدل ملفك التعريفي</string>
|
||||
<string name="title_saved_toot">المسودات</string>
|
||||
<string name="title_licenses">الرّخص</string>
|
||||
<string name="status_username_format">\@%s</string>
|
||||
<string name="status_boosted_format">%s رقّي</string>
|
||||
<string name="status_boosted_format">شارَكَه %s</string>
|
||||
<string name="status_sensitive_media_title">محتوى حساس</string>
|
||||
<string name="status_media_hidden_title">وسائط مخفية</string>
|
||||
<string name="status_sensitive_media_directions">اضغط للعرض</string>
|
||||
<string name="status_content_warning_show_more">اعرض أكثر</string>
|
||||
<string name="status_content_warning_show_more">اعرض المزيد</string>
|
||||
<string name="status_content_warning_show_less">اعرض أقل</string>
|
||||
<string name="status_content_show_more">توسيع</string>
|
||||
<string name="status_content_show_less">تصغير</string>
|
||||
<string name="message_empty">لا شيء هنا.</string>
|
||||
<string name="footer_empty">لا يوجد شيئ هنا. إسحب إلى أسفل للتحديث !</string>
|
||||
<string name="notification_reblog_format">رقّى %s تبويقك</string>
|
||||
<string name="footer_empty">لا يوجد شيء هنا. إسحب إلى أسفل للإنعاش!</string>
|
||||
<string name="notification_reblog_format">شارَك %s تبويقك</string>
|
||||
<string name="notification_favourite_format">أعجِب %s بتبويقك</string>
|
||||
<string name="notification_follow_format">%s يتبعك</string>
|
||||
<string name="report_username_format">أبلغ عن @%s</string>
|
||||
<string name="report_comment_hint">تعليقات إضافية ؟</string>
|
||||
<string name="action_quick_reply">إجابة سريعة</string>
|
||||
<string name="action_reply">أجب</string>
|
||||
<string name="report_comment_hint">تعليقات إضافية؟</string>
|
||||
<string name="action_quick_reply">رد سريع</string>
|
||||
<string name="action_reply">رد</string>
|
||||
<string name="action_reblog">رقّي</string>
|
||||
<string name="action_unreblog">إزالة الترقية</string>
|
||||
<string name="action_favourite">تفضيل</string>
|
||||
<string name="action_unfavourite">إزالة المفضلة</string>
|
||||
<string name="action_more">المزيد</string>
|
||||
<string name="action_compose">حرر</string>
|
||||
<string name="action_login">التسجيل بواسطة ماستدون</string>
|
||||
<string name="action_login">الولوج إلى ماستدون</string>
|
||||
<string name="action_logout">خروج</string>
|
||||
<string name="action_logout_confirm">متأكد مِن أنك تود الخروج من الحساب %1$s ؟</string>
|
||||
<string name="action_logout_confirm">متأكد مِن أنك تود الخروج من الحساب %1$s؟</string>
|
||||
<string name="action_follow">إتبع</string>
|
||||
<string name="action_unfollow">إلغاء التتبع</string>
|
||||
<string name="action_unfollow">إلغاء المتابعة</string>
|
||||
<string name="action_block">قم بحظره</string>
|
||||
<string name="action_unblock">إلغاء الحظر</string>
|
||||
<string name="action_hide_reblogs">إخفاء الترقيات</string>
|
||||
<string name="action_show_reblogs">إظهار الترقيات</string>
|
||||
<string name="action_report">أبلغ</string>
|
||||
<string name="action_report">أبلغ عنه</string>
|
||||
<string name="action_delete">إحذف</string>
|
||||
<string name="action_send">بَوّق</string>
|
||||
<string name="action_send_public">بوّق!</string>
|
||||
<string name="action_retry">إعادة المحاولة</string>
|
||||
<string name="action_retry">أعد المحاولة</string>
|
||||
<string name="action_close">إغلاق</string>
|
||||
<string name="action_view_profile">الملف الشخصي</string>
|
||||
<string name="action_view_profile">الملف التعريفي</string>
|
||||
<string name="action_view_preferences">التفضيلات</string>
|
||||
<string name="action_view_account_preferences">تفضيلات الحساب</string>
|
||||
<string name="action_view_favourites">المفضلة</string>
|
||||
@ -95,7 +95,7 @@
|
||||
<string name="action_hide_media">إخفاء الوسائط</string>
|
||||
<string name="action_open_drawer">إفتح الدرج</string>
|
||||
<string name="action_save">إحفظ</string>
|
||||
<string name="action_edit_profile">تعديل الملف الشخصي</string>
|
||||
<string name="action_edit_profile">تعديل الملف التعريفي</string>
|
||||
<string name="action_edit_own_profile">تعديل</string>
|
||||
<string name="action_undo">إلغاء</string>
|
||||
<string name="action_accept">موافقة</string>
|
||||
@ -109,8 +109,8 @@
|
||||
<string name="action_links">الروابط</string>
|
||||
<string name="action_mentions">الإشارات</string>
|
||||
<string name="action_hashtags">الوسوم</string>
|
||||
<string name="action_open_reblogged_by">عرض الترقيات</string>
|
||||
<string name="action_open_faved_by">عرض المفضلات</string>
|
||||
<string name="action_open_reblogged_by">اعرض الترقيات</string>
|
||||
<string name="action_open_faved_by">اعرض المفضلات</string>
|
||||
<string name="title_hashtags_dialog">الوسوم</string>
|
||||
<string name="title_mentions_dialog">الإشارات</string>
|
||||
<string name="title_links_dialog">الروابط</string>
|
||||
@ -120,23 +120,23 @@
|
||||
<string name="action_share_as">شاركه كـ…</string>
|
||||
<string name="send_status_link_to">شارك رابط التبويق مع…</string>
|
||||
<string name="send_status_content_to">شارك التبويق على…</string>
|
||||
<string name="send_media_to">شارك رابط التبويق مع…</string>
|
||||
<string name="confirmation_reported">تم الإرسال !</string>
|
||||
<string name="send_media_to">شارك الوسيط مع…</string>
|
||||
<string name="confirmation_reported">تم إرساله!</string>
|
||||
<string name="confirmation_unblocked">تم فك الحجب عن الحساب</string>
|
||||
<string name="confirmation_unmuted">تم فك الكتم عن الحساب</string>
|
||||
<string name="status_sent">تم إرساله !</string>
|
||||
<string name="confirmation_unmuted">لم يعد الحساب مكتومًا</string>
|
||||
<string name="status_sent">تم إرساله!</string>
|
||||
<string name="status_sent_long">تم إرسال الرد بنجاح.</string>
|
||||
<string name="hint_domain">أي سيرفر ؟</string>
|
||||
<string name="hint_compose">ما الجديد ؟</string>
|
||||
<string name="hint_domain">أي مثيل خادم؟</string>
|
||||
<string name="hint_compose">ما الجديد؟</string>
|
||||
<string name="hint_content_warning">تحذير عن المحتوى</string>
|
||||
<string name="hint_display_name">الإسم العلني</string>
|
||||
<string name="hint_note">السيرة</string>
|
||||
<string name="hint_search">البحث عن…</string>
|
||||
<string name="search_no_results">لم يتم العثور على نتائج</string>
|
||||
<string name="label_quick_reply">إجابة …</string>
|
||||
<string name="label_avatar">الصورة الرمزية</string>
|
||||
<string name="label_header">رأس الصفحة</string>
|
||||
<string name="link_whats_an_instance">ماذا نعني بمثيل الخادم ؟</string>
|
||||
<string name="search_no_results">لم يتم العثور على أية نتائج</string>
|
||||
<string name="label_quick_reply">رد…</string>
|
||||
<string name="label_avatar">صورة الملف التعريفي</string>
|
||||
<string name="label_header">صورة رأس الصفحة</string>
|
||||
<string name="link_whats_an_instance">ماذا نعني بمثيل الخادم؟</string>
|
||||
<string name="login_connection">الإتصال جارٍ…</string>
|
||||
<string name="dialog_whats_an_instance">بإمكانك إدخال عنوان أي مثيل خادوم ماستدون هنا. على سبيل المثال mastodon.social أو icosahedron.website أو social.tchncs.de أوالإطلاع على <a href="https://instances.social">لاكتشاف المزيد !</a>
|
||||
\n
|
||||
@ -148,13 +148,13 @@
|
||||
<string name="dialog_title_finishing_media_upload">تتمة رفع الوسائط</string>
|
||||
<string name="dialog_message_uploading_media">الإرسال جارٍ…</string>
|
||||
<string name="dialog_download_image">تنزيل</string>
|
||||
<string name="dialog_message_cancel_follow_request">هل تريد رفض طلب المتابعة ؟</string>
|
||||
<string name="dialog_unfollow_warning">هل تود إلغاء متابعة هذا الحساب ؟</string>
|
||||
<string name="dialog_message_cancel_follow_request">هل تريد رفض طلب المتابعة؟</string>
|
||||
<string name="dialog_unfollow_warning">هل تود إلغاء متابعة هذا الحساب؟</string>
|
||||
<string name="dialog_delete_toot_warning">هل تريد حذف هذا التبويق؟</string>
|
||||
<string name="visibility_public">عمومي : ينشر على الخيوط العمومية</string>
|
||||
<string name="visibility_unlisted">غير مدرج : لا يُعرَض على الخيوط العمومية</string>
|
||||
<string name="visibility_private">لمتابعيك فقط : يُنشر إلى متابعيك فقط</string>
|
||||
<string name="visibility_direct">مباشر : يُنشر إلى المستخدمين المشار إليهم فقط</string>
|
||||
<string name="visibility_public">للعامة: ينشر على الخيوط العمومية</string>
|
||||
<string name="visibility_unlisted">غير مدرج: لا يُعرَض على الخيوط العمومية</string>
|
||||
<string name="visibility_private">لمتابعيك فقط: يُنشر إلى متابعيك فقط</string>
|
||||
<string name="visibility_direct">مباشر: يُنشر إلى المستخدمين المشار إليهم فقط</string>
|
||||
<string name="pref_title_edit_notification_settings">تعديل الاشعارات</string>
|
||||
<string name="pref_title_notifications_enabled">الإخطارات</string>
|
||||
<string name="pref_title_notification_alerts">التنبيهات</string>
|
||||
@ -163,12 +163,12 @@
|
||||
<string name="pref_title_notification_alert_light">إعلام بالضوء</string>
|
||||
<string name="pref_title_notification_filters">أخطرني عندما</string>
|
||||
<string name="pref_title_notification_filter_mentions">يشار إلي</string>
|
||||
<string name="pref_title_notification_filter_follows">يتبعني أحد</string>
|
||||
<string name="pref_title_notification_filter_follows">يتبعني أحدهم</string>
|
||||
<string name="pref_title_notification_filter_reblogs">تُرقّى منشوراتي</string>
|
||||
<string name="pref_title_notification_filter_favourites">أعجب أحد ما بمنشوراتي</string>
|
||||
<string name="pref_title_notification_filter_favourites">يُعجَب أحد ما بمنشوراتي</string>
|
||||
<string name="pref_title_appearance_settings">المظهر</string>
|
||||
<string name="pref_title_app_theme">سمة التطبيق</string>
|
||||
<string name="pref_title_timelines">الخيوط</string>
|
||||
<string name="pref_title_app_theme">حُلّة التطبيق</string>
|
||||
<string name="pref_title_timelines">الخيوط الزمنية</string>
|
||||
<string name="pref_title_timeline_filters">عوامل التصفية</string>
|
||||
<string name="app_them_dark">داكنة</string>
|
||||
<string name="app_theme_light">فاتحة</string>
|
||||
@ -339,7 +339,7 @@
|
||||
<string name="action_open_reblogger">إظهار صاحب الترقية</string>
|
||||
<string name="action_open_media_n">افتح الوسيط #%d</string>
|
||||
|
||||
<string name="download_media">تنزيل الوسائط</string>
|
||||
<string name="download_media">نزّل الوسائط</string>
|
||||
<string name="downloading_media">جارٍ تنزيل الوسائط</string>
|
||||
|
||||
<string name="dialog_redraft_toot_warning">هل تريد حذف وإعادة صياغة هذا التبويق؟</string>
|
||||
@ -378,7 +378,7 @@
|
||||
<string name="poll_ended_created">لقد انتهى استطلاع رأي قمتَ بإنشائه</string>
|
||||
|
||||
|
||||
<string name="pref_title_notification_filter_poll">انتهت استطلاعات الرأي</string>
|
||||
<string name="pref_title_notification_filter_poll">تنتهي استطلاعات الرأي</string>
|
||||
<plurals name="favs">
|
||||
<item quantity="zero"><b>%1$s</b>" مفضلة"</item>
|
||||
<item quantity="one"><b>%1$s</b> مفضلة</item>
|
||||
@ -457,7 +457,7 @@
|
||||
<string name="filter_dialog_whole_word">الكلمة كاملة</string>
|
||||
<string name="description_poll">استطلاع رأي بالخيارات: %1$s, %2$s, %3$s, %4$s; %5$s</string>
|
||||
|
||||
<string name="mute_domain_warning">هل أنت متأكد من أنك تريد حجب كافة %s ؟ سوف لن يكون باستطاعتك رؤية أي محتوى قادم من هذا النطاق بعد الآن ، لا في الخيوط الزمنية العامة ولا في إخطاراتك. سيتم إزالة متابِعيك الذين هم على هذا النطاق.</string>
|
||||
<string name="mute_domain_warning">هل أنت متأكد من أنك تريد حجب كافة %s؟ سوف لن يكون باستطاعتك رؤية أي محتوى قادم من هذا النطاق بعد الآن ، لا في الخيوط الزمنية العامة ولا في إخطاراتك. سيتم إزالة متابِعيك الذين هم على هذا النطاق.</string>
|
||||
<string name="report_description_1">سيتم إرسال التقرير إلى مشرفي خادمك. يمكنك تقديم تفسير عن سبب الإبلاغ عن الحساب أدناه:</string>
|
||||
<string name="report_description_remote_instance">هذا الحساب ينتسب إلى خادم آخر. هل تريد إرسال نسخة مجهولة من التقرير إلى هناك أيضا؟</string>
|
||||
|
||||
@ -501,4 +501,6 @@
|
||||
<string name="no_scheduled_status">ليس لديك أية منشورات مُبرمَجة للنشر.</string>
|
||||
|
||||
<string name="error_audio_upload_size">يجب أن يكون حجم الملفات الصوتية أقل مِن 40 ميغابايت.</string>
|
||||
</resources>
|
||||
<string name="warning_scheduling_interval">تُقدّر أدنى فترة لبرمجة النشر في ماستدون بـ 5 دقائق.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -534,4 +534,7 @@
|
||||
|
||||
<string name="no_scheduled_status">No tens cap estat planificat.</string>
|
||||
|
||||
</resources>
|
||||
<string name="error_audio_upload_size">Els fitxers d\'àudio han de ser més petits de 40MB.</string>
|
||||
<string name="no_saved_status">No tens cap esborrany.</string>
|
||||
<string name="warning_scheduling_interval">L\'interval mínim de planificació a Mastodon és de 5 minuts.</string>
|
||||
</resources>
|
||||
|
2
app/src/main/res/values-en-rAU/strings.xml
Normal file
2
app/src/main/res/values-en-rAU/strings.xml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
@ -469,4 +469,9 @@
|
||||
<string name="list">Listo</string>
|
||||
<string name="post_lookup_error_format">Eraro dum elserĉo de la mesaĝo %s</string>
|
||||
|
||||
</resources>
|
||||
<string name="error_audio_upload_size">Aŭdia dosiero devas esti malpli ol 40MB.</string>
|
||||
<string name="gradient_for_media">Montri buntajn transirojn por kaŝitaj aŭdovidaĵoj</string>
|
||||
|
||||
<string name="no_saved_status">Vi ne havas iun ajn malneton.</string>
|
||||
<string name="no_scheduled_status">Vi ne havas iun ajn planitan mesaĝon.</string>
|
||||
</resources>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<string name="error_network">¡Se ha producido un error de red! ¡Por favor, comprueba tu conexión e inténtalo de nuevo!</string>
|
||||
<string name="error_empty">Este campo no puede estar vacío.</string>
|
||||
<string name="error_invalid_domain">Nombre de dominio incorrecto</string>
|
||||
<string name="error_failed_app_registration">Inicio de sesión fallido.</string>
|
||||
<string name="error_failed_app_registration">Fallo de autenticación con esta instancia.</string>
|
||||
<string name="error_no_web_browser_found">No se ha encontrado ningún navegador web.</string>
|
||||
<string name="error_authorization_unknown">Ocurrió un error de autorización no identificado.</string>
|
||||
<string name="error_authorization_denied">La autorización falló.</string>
|
||||
@ -474,9 +474,10 @@
|
||||
<string name="select_list_title">Seleccionar lista</string>
|
||||
<string name="list">Lista</string>
|
||||
<string name="error_audio_upload_size">Los ficheros de audio deben ser menores de 40MB.</string>
|
||||
<string name="gradient_for_media">Mostrar degradados coloridos para el contenido multimedia oculto.</string>
|
||||
<string name="gradient_for_media">Mostrar degradados coloridos para el contenido multimedia oculto</string>
|
||||
|
||||
<string name="no_saved_status">No tienes ningún borrador.</string>
|
||||
<string name="no_scheduled_status">No tienes ningún estado programado.</string>
|
||||
|
||||
</resources>
|
||||
<string name="warning_scheduling_interval">Mastodon tiene un intervalo de programación mínimo de 5 minutos.</string>
|
||||
</resources>
|
||||
|
@ -39,7 +39,7 @@
|
||||
<string name="title_saved_toot">Brouillons</string>
|
||||
<string name="title_licenses">Licences</string>
|
||||
<string name="status_username_format">\@%s</string>
|
||||
<string name="status_boosted_format">%s a boosté</string>
|
||||
<string name="status_boosted_format">%s a partagé</string>
|
||||
<string name="status_sensitive_media_title">Contenu sensible</string>
|
||||
<string name="status_media_hidden_title">Média caché</string>
|
||||
<string name="status_sensitive_media_directions">Cliquer pour voir</string>
|
||||
@ -49,15 +49,15 @@
|
||||
<string name="status_content_show_less">Replier</string>
|
||||
<string name="message_empty">Rien ici.</string>
|
||||
<string name="footer_empty">Il n’y a aucun pouet pour le moment.\nGlissez vers le bas pour actualiser !</string>
|
||||
<string name="notification_reblog_format">%s a boosté votre pouet</string>
|
||||
<string name="notification_reblog_format">%s a partagé votre pouet</string>
|
||||
<string name="notification_favourite_format">%s a ajouté votre pouet à ses favoris</string>
|
||||
<string name="notification_follow_format">%s vous suit</string>
|
||||
<string name="report_username_format">Signaler @%s</string>
|
||||
<string name="report_comment_hint">Commentaires additonnels ?</string>
|
||||
<string name="action_quick_reply">Réponse rapide</string>
|
||||
<string name="action_reply">Répondre</string>
|
||||
<string name="action_reblog">Booster</string>
|
||||
<string name="action_unreblog">Supprimer le boost</string>
|
||||
<string name="action_reblog">Partager</string>
|
||||
<string name="action_unreblog">Annuler le partage</string>
|
||||
<string name="action_favourite">Favori</string>
|
||||
<string name="action_unfavourite">Supprimer le favori</string>
|
||||
<string name="action_more">Plus</string>
|
||||
@ -69,8 +69,8 @@
|
||||
<string name="action_unfollow">Ne plus suivre</string>
|
||||
<string name="action_block">Bloquer</string>
|
||||
<string name="action_unblock">Débloquer</string>
|
||||
<string name="action_hide_reblogs">Cacher les boosts</string>
|
||||
<string name="action_show_reblogs">Montrer les boosts</string>
|
||||
<string name="action_hide_reblogs">Cacher les partages</string>
|
||||
<string name="action_show_reblogs">Montrer les partages</string>
|
||||
<string name="action_report">Signaler</string>
|
||||
<string name="action_delete">Supprimer</string>
|
||||
<string name="action_send">POUET</string>
|
||||
@ -109,8 +109,8 @@
|
||||
<string name="action_links">Liens</string>
|
||||
<string name="action_mentions">Mentions</string>
|
||||
<string name="action_hashtags">Hashtags</string>
|
||||
<string name="action_open_reblogger">Afficher l’auteur·rice du boost</string>
|
||||
<string name="action_open_reblogged_by">Afficher les boosts</string>
|
||||
<string name="action_open_reblogger">Afficher l’auteur·rice du partage</string>
|
||||
<string name="action_open_reblogged_by">Montrer les partages</string>
|
||||
<string name="action_open_faved_by">Montrer les favoris</string>
|
||||
<string name="title_hashtags_dialog">Hashtags</string>
|
||||
<string name="title_mentions_dialog">Mentions</string>
|
||||
@ -170,7 +170,7 @@
|
||||
<string name="pref_title_notification_filters">Me notifier lorsque</string>
|
||||
<string name="pref_title_notification_filter_mentions">on me mentionne</string>
|
||||
<string name="pref_title_notification_filter_follows">on me suit</string>
|
||||
<string name="pref_title_notification_filter_reblogs">mes messages sont boostés</string>
|
||||
<string name="pref_title_notification_filter_reblogs">mes pouets sont partagés</string>
|
||||
<string name="pref_title_notification_filter_favourites">mes messages sont mis en favoris</string>
|
||||
<string name="pref_title_appearance_settings">Apparence</string>
|
||||
<string name="pref_title_app_theme">Thème de l’application</string>
|
||||
@ -187,7 +187,7 @@
|
||||
<string name="pref_title_language">Langue</string>
|
||||
<string name="pref_title_status_filter">Filtrage des fils</string>
|
||||
<string name="pref_title_status_tabs">Onglets</string>
|
||||
<string name="pref_title_show_boosts">Afficher les boosts</string>
|
||||
<string name="pref_title_show_boosts">Montrer les partages</string>
|
||||
<string name="pref_title_show_replies">Afficher les réponses</string>
|
||||
<string name="pref_title_show_media_preview">Montrer les miniatures des médias</string>
|
||||
<string name="pref_title_proxy_settings">Proxy</string>
|
||||
@ -213,7 +213,7 @@
|
||||
<string name="notification_follow_name">Nouveaux abonnés</string>
|
||||
<string name="notification_follow_description">Notifications pour les nouveaux abonnés</string>
|
||||
<string name="notification_boost_name">Partages</string>
|
||||
<string name="notification_boost_description">Notifications quand vos pouets sont boostés</string>
|
||||
<string name="notification_boost_description">Notifications quand vos pouets sont partagés</string>
|
||||
<string name="notification_favourite_name">Favoris</string>
|
||||
<string name="notification_favourite_description">Notifications quand vos pouets sont mis en favoris</string>
|
||||
<string name="notification_mention_format">%s vous a mentionné</string>
|
||||
@ -316,8 +316,8 @@
|
||||
<string name="download_failed">Échec du téléchargement</string>
|
||||
<string name="profile_badge_bot_text">Robot</string>
|
||||
<string name="account_moved_description">%1$s a déménagé vers :</string>
|
||||
<string name="reblog_private">Booster vers l’audience originale</string>
|
||||
<string name="unreblog_private">Ne plus booster</string>
|
||||
<string name="reblog_private">Partager à l’audience originale</string>
|
||||
<string name="unreblog_private">Annuler le partage</string>
|
||||
<string name="license_description">Yuito contient du code et des ressources issus des projets open source suivants :</string>
|
||||
<string name="license_apache_2">Sous licence Apache (copie ci-dessous)</string>
|
||||
<string name="license_cc_by_4">CC-BY 4.0</string>
|
||||
@ -335,10 +335,10 @@
|
||||
<item quantity="other"><b>%1$s</b> Favoris</item>
|
||||
</plurals>
|
||||
<plurals name="reblogs">
|
||||
<item quantity="one"><b>%s</b> Boost</item>
|
||||
<item quantity="other"><b>%s</b> Boosts</item>
|
||||
</plurals>
|
||||
<string name="title_reblogged_by">Boosté par</string>
|
||||
<item quantity="one"><b>%s</b> Partage</item>
|
||||
<item quantity="other"><b>%s</b> Partages</item>
|
||||
</plurals>
|
||||
<string name="title_reblogged_by">Partagé par</string>
|
||||
<string name="title_favourited_by">Mis en favoris par</string>
|
||||
<string name="conversation_1_recipients">%1$s</string>
|
||||
<string name="conversation_2_recipients">%1$s et %2$s</string>
|
||||
@ -371,7 +371,7 @@
|
||||
<string name="notifications_apply_filter">Filtrer</string>
|
||||
<string name="filter_apply">Appliquer</string>
|
||||
|
||||
<string name="compose_shortcut_long_label">Écrire un pouet</string>
|
||||
<string name="compose_shortcut_long_label">Rédiger un pouet</string>
|
||||
<string name="compose_shortcut_short_label">Écrire</string>
|
||||
<string name="pref_title_bot_overlay">Afficher l\'indicateur de robots</string>
|
||||
|
||||
@ -486,4 +486,6 @@
|
||||
<string name="no_saved_status">Vous n’avez aucun brouillon.</string>
|
||||
<string name="no_scheduled_status">Vous n’avez aucun pouet planifié.</string>
|
||||
|
||||
<string name="warning_scheduling_interval">L’intervalle minimum de planification sur Mastodon est de 5 minutes.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -508,4 +508,6 @@
|
||||
<string name="no_scheduled_status">Þú ert ekki með neinar áætlaðar stöðufærslur.</string>
|
||||
|
||||
<string name="error_audio_upload_size">Hljóðskrár verða að vera minni en 40MB.</string>
|
||||
</resources>
|
||||
<string name="warning_scheduling_interval">Mastodon er með 5 mínútna lágmarksbil fyrir áætlaðar aðgerðir.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -420,4 +420,10 @@
|
||||
<string name="pref_title_show_notifications_filter">通知フィルターを表示</string>
|
||||
|
||||
|
||||
<string name="action_reset_schedule">リセット</string>
|
||||
<string name="error_audio_upload_size">音声ファイルは40MB未満にしてください。</string>
|
||||
<string name="title_bookmarks">ブックマーク</string>
|
||||
<string name="action_bookmark">ブックマーク</string>
|
||||
<string name="action_edit">編集</string>
|
||||
<string name="action_view_bookmarks">ブックマーク</string>
|
||||
</resources>
|
||||
|
@ -1,22 +1,22 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources><string name="action_login">Qqen γer Maṣṭudun</string>
|
||||
<resources><string name="action_login">Qqen ɣer Maṣṭudun</string>
|
||||
<string name="title_favourites">Ismenyifen</string>
|
||||
<string name="title_saved_toot">Irewwayen</string>
|
||||
<string name="action_logout">Ffeγ</string>
|
||||
<string name="action_view_preferences">Iγewwaṛen</string>
|
||||
<string name="action_view_account_preferences">Iγewwaṛen n umiḍan</string>
|
||||
<string name="action_edit_profile">Ẓreg amaγnu</string>
|
||||
<string name="action_logout">Ffeɣ</string>
|
||||
<string name="action_view_preferences">Iɣewwaṛen</string>
|
||||
<string name="action_view_account_preferences">Iɣewwaṛen n umiḍan</string>
|
||||
<string name="action_edit_profile">Ẓreg amaɣnu</string>
|
||||
<string name="action_search">Nadi</string>
|
||||
<string name="about_title_activity">Γef</string>
|
||||
<string name="action_lists">Umuγen</string>
|
||||
<string name="title_lists">Umuγen</string>
|
||||
<string name="error_compose_character_limit">Tijewwiqt-ik aṭas i γuzzifet!</string>
|
||||
<string name="about_title_activity">Ɣef</string>
|
||||
<string name="action_lists">Umuɣen</string>
|
||||
<string name="title_lists">Umuɣen</string>
|
||||
<string name="error_compose_character_limit">Tijewwiqt-ik aṭas i ɣuzzifet!</string>
|
||||
<string name="title_home">Agejdan</string>
|
||||
<string name="title_tab_preferences">Iccaren</string>
|
||||
<string name="title_view_thread">Tijewwiqt</string>
|
||||
<string name="title_statuses">Iznan</string>
|
||||
<string name="title_statuses_with_replies">S tririyin</string>
|
||||
<string name="title_edit_profile">Ẓreg amaγnu-ik</string>
|
||||
<string name="title_edit_profile">Ẓreg amaɣnu-ik</string>
|
||||
<string name="status_username_format">\@%s</string>
|
||||
<string name="status_content_warning_show_more">Zeṛ ugar</string>
|
||||
<string name="status_content_warning_show_less">Zeṛ kra kan</string>
|
||||
@ -35,13 +35,13 @@
|
||||
<string name="action_send_public">JEWWEQ!</string>
|
||||
<string name="action_retry">Ɛreḍ tikkelt-nniḍen</string>
|
||||
<string name="action_close">Derreɛ</string>
|
||||
<string name="action_view_profile">Amaγnu</string>
|
||||
<string name="action_view_profile">Amaɣnu</string>
|
||||
<string name="action_view_favourites">Ismenyifen</string>
|
||||
<string name="action_open_in_web">Ldi deg uminig</string>
|
||||
<string name="action_share">Bḍu</string>
|
||||
<string name="action_mute">Sgugem</string>
|
||||
<string name="action_access_saved_toot">Irewwayen</string>
|
||||
<string name="action_open_faved_by">Sken-ed ismenyifen</string>
|
||||
<string name="action_open_faved_by">Sken-d ismenyifen</string>
|
||||
|
||||
<string name="notification_favourite_name">Ismenyifen</string>
|
||||
<plurals name="favs">
|
||||
@ -51,11 +51,11 @@
|
||||
|
||||
<string name="no_saved_status">Ur tesɛiḍ ara irewwayen.</string>
|
||||
<string name="error_generic">Tella-d tucḍa.</string>
|
||||
<string name="title_notifications">Tilγa</string>
|
||||
<string name="title_notifications">Tilɣa</string>
|
||||
<string name="link_whats_an_instance">D acu i ttummant\?</string>
|
||||
|
||||
<string name="title_bookmarks">Ticraḍ</string>
|
||||
<string name="action_bookmark">Rnu γer ticraḍ</string>
|
||||
<string name="action_bookmark">Rnu ɣer ticraḍ</string>
|
||||
<string name="action_view_bookmarks">Ticraḍ</string>
|
||||
<string name="action_mute_domain">Sgugem %s</string>
|
||||
<string name="action_mention">Bder</string>
|
||||
@ -64,20 +64,20 @@
|
||||
<string name="action_undo">Sefsex</string>
|
||||
<string name="action_emoji_keyboard">Anasiw n imujiyen</string>
|
||||
<string name="action_add_tab">Rnu iccer</string>
|
||||
<string name="action_copy_link">Nγel aseγwen</string>
|
||||
<string name="action_copy_link">Nɣel aseɣwen</string>
|
||||
<string name="action_open_as">Ldi amzun d %s</string>
|
||||
<string name="action_share_as">Bḍu amzun d…</string>
|
||||
<string name="send_status_link_to">Bḍu aseγwen n tijewwiq s…</string>
|
||||
<string name="send_status_link_to">Bḍu aseɣwen n tijewwiq s…</string>
|
||||
<string name="send_status_content_to">Bḍu tijewwiqt d…</string>
|
||||
<string name="hint_domain">Anta tummant\?</string>
|
||||
<string name="hint_compose">d-acu i gellan d amaynut\?</string>
|
||||
<string name="hint_search">Nadi…</string>
|
||||
|
||||
<string name="label_quick_reply">Tiririn…</string>
|
||||
<string name="label_avatar">Tugna n umaγnu</string>
|
||||
<string name="label_avatar">Tugna n umaɣnu</string>
|
||||
<string name="dialog_download_image">Sider</string>
|
||||
<string name="dialog_delete_toot_warning">Kkes tijewwiqt-a\?</string>
|
||||
<string name="pref_title_edit_notification_settings">Ẓreg tilγa</string>
|
||||
<string name="pref_title_edit_notification_settings">Ẓreg tilɣa</string>
|
||||
<string name="pref_title_appearance_settings">Agrudem</string>
|
||||
<string name="app_theme_light">Aceɛlal</string>
|
||||
<string name="app_theme_black">Aberkan</string>
|
||||
@ -88,7 +88,7 @@
|
||||
<string name="notification_summary_medium">%1$s, %2$s, akked %3$s</string>
|
||||
<string name="notification_summary_small">%1$s akked %2$s</string>
|
||||
<string name="about_tusky_version">Tusky %s</string>
|
||||
<string name="about_tusky_account">Amaγnu n Tusky</string>
|
||||
<string name="about_tusky_account">Amaɣnu n Tusky</string>
|
||||
|
||||
<string name="status_media_images">Tugniwin</string>
|
||||
<string name="status_media_video">Tibidyutin</string>
|
||||
@ -109,17 +109,17 @@
|
||||
<string name="pin_action">Senṭeḍ</string>
|
||||
|
||||
<string name="action_view_mutes">Imiḍanen yettwasgugmen</string>
|
||||
<string name="action_view_blocks">Imiḍanen yettusḥebsen</string>
|
||||
<string name="action_view_domain_mutes">Tiγula yettwaffren</string>
|
||||
<string name="action_view_blocks">Imiḍan yettwacekklen</string>
|
||||
<string name="action_view_domain_mutes">Tiɣula yettwaffren</string>
|
||||
<string name="action_view_follow_requests">Isuturen n teḍfeṛt</string>
|
||||
<string name="action_view_media">Taγwalt</string>
|
||||
<string name="action_view_media">Taɣwalt</string>
|
||||
<string name="notifications_clear">Sfeḍ</string>
|
||||
<string name="title_mutes">Imiḍanen yettwasgugmen</string>
|
||||
<string name="title_blocks">Imiḍanen yettusḥebsen</string>
|
||||
<string name="title_domain_mutes">Tiγula yettwaffren</string>
|
||||
<string name="title_blocks">Imiḍanen yettwacekklen</string>
|
||||
<string name="title_domain_mutes">Tiɣula yettwaffren</string>
|
||||
<string name="title_follow_requests">Isuturen n teḍfeṛt</string>
|
||||
<string name="pref_title_notifications_enabled">Ẓreg tilγa</string>
|
||||
<string name="title_media">Taγwalt</string>
|
||||
<string name="pref_title_notifications_enabled">Tilɣa</string>
|
||||
<string name="title_media">Taywalt</string>
|
||||
<string name="action_remove">Kkes</string>
|
||||
<string name="compose_shortcut_short_label">Azen</string>
|
||||
|
||||
@ -129,28 +129,28 @@
|
||||
<string name="action_add_poll">Rnu assenqed</string>
|
||||
<string name="action_photo_take">Ṭef tugna</string>
|
||||
<string name="action_toggle_visibility">Timeẓriwt n tijewwaqt</string>
|
||||
<string name="action_schedule_toot">Sγiwes tijewwaqt-a</string>
|
||||
<string name="action_schedule_toot">Sɣiwes tijewwaqt-a</string>
|
||||
<string name="status_share_content">Bḍu agbur n tijewwiqt-a</string>
|
||||
<string name="status_share_link">Bḍu aseγwen γer tijewwiqt</string>
|
||||
<string name="status_share_link">Bḍu aseɣwen ɣer tijewwiqt</string>
|
||||
<string name="filter_addition_dialog_title">Rnu amsizdeg</string>
|
||||
<string name="filter_edit_dialog_title">Ẓreg amsizdeg</string>
|
||||
<string name="action_create_list">Snulfu-d umuγ</string>
|
||||
<string name="action_rename_list">Snifel isem n wumuγ</string>
|
||||
<string name="action_delete_list">Kkes umuγ-a</string>
|
||||
<string name="action_edit_list">Ẓreg umuγ-a</string>
|
||||
<string name="action_add_to_list">Rnu yiwen umiḍan γer tabdert</string>
|
||||
<string name="action_remove_from_list">Kkes amiḍan seg wumuγ</string>
|
||||
<string name="action_create_list">Snulfu-d umuɣ</string>
|
||||
<string name="action_rename_list">Snifel isem n wumuɣ</string>
|
||||
<string name="action_delete_list">Kkes umuɣ-a</string>
|
||||
<string name="action_edit_list">Ẓreg umuɣ-a</string>
|
||||
<string name="action_add_to_list">Rnu yiwen umiḍan ɣer wummuɣ</string>
|
||||
<string name="action_remove_from_list">Kkes amiḍan seg wumuɣ</string>
|
||||
|
||||
<string name="profile_metadata_add">Rnu isefka</string>
|
||||
<string name="hint_list_name">Isem n wumuγ</string>
|
||||
<string name="hint_list_name">Isem n wumuɣ</string>
|
||||
|
||||
<string name="select_list_title">Fren tabdart</string>
|
||||
<string name="list">Umuγ</string>
|
||||
<string name="list">Umuɣ</string>
|
||||
<string name="notifications_apply_filter">Sizdeg</string>
|
||||
<string name="title_accounts">Imiḍanen</string>
|
||||
<string name="add_poll_choice">Rnu yiwen wefran</string>
|
||||
<string name="report_username_format">Ccetki γef @%s</string>
|
||||
<string name="action_report">Ccetki</string>
|
||||
<string name="report_username_format">Ccetki ɣef @%s</string>
|
||||
<string name="action_report">Ccetki fell-as</string>
|
||||
<string name="action_reject">Ggami</string>
|
||||
<string name="download_image">Yessidired %1$s</string>
|
||||
|
||||
@ -159,16 +159,16 @@
|
||||
<string name="login_connection">itteqqen…</string>
|
||||
|
||||
<string name="dialog_message_uploading_media">Issalay…</string>
|
||||
<string name="pref_title_notification_filter_poll">fukken kran n wadγaren</string>
|
||||
<string name="pref_title_notification_filter_poll">fukken kran n wadɣaren</string>
|
||||
<string name="pref_title_timeline_filters">Imzizdigen</string>
|
||||
|
||||
<string name="app_theme_auto">Akken yella yiṭij</string>
|
||||
<string name="pref_title_browser_settings">Iminig</string>
|
||||
<string name="pref_title_show_replies">Sken-ed tiririyin</string>
|
||||
<string name="pref_title_show_replies">Sken-d tiririyin</string>
|
||||
<string name="pref_title_http_proxy_settings">Apṛuksi HTTP</string>
|
||||
<string name="pref_title_http_proxy_server">Tansa n upṛuksi HTTP</string>
|
||||
<string name="notification_follow_name">Imeḍfaṛen imaynuten</string>
|
||||
<string name="notification_poll_name">Adγaren</string>
|
||||
<string name="notification_poll_name">Adɣaren</string>
|
||||
<string name="notification_mention_format">Yuder-ik-id %s</string>
|
||||
<string name="description_account_locked">Yettwargel umiḍan</string>
|
||||
|
||||
@ -183,26 +183,26 @@
|
||||
<string name="restart">Ales tanekra</string>
|
||||
<string name="download_failed">Tuccḍa n usider</string>
|
||||
|
||||
<string name="account_moved_description">Igujj %1$s γer:</string>
|
||||
<string name="account_moved_description">Igujj %1$s ɣer:</string>
|
||||
|
||||
<string name="unpin_action">Kkes asenṭeḍ</string>
|
||||
<string name="conversation_1_recipients">%1$s</string>
|
||||
<string name="conversation_2_recipients">%1$s akked %2$s</string>
|
||||
<string name="conversation_more_recipients">%1$s, %2$s akked %3$d nniḍen</string>
|
||||
<string name="compose_shortcut_long_label">Aru tijewwiqt</string>
|
||||
<string name="poll_info_format"> <!-- 15 n wadγaren • 1 n wesrag id yeqqimen --> %1$s • %2$s</string>
|
||||
<string name="poll_info_format"> <!-- 15 n wadɣaren • 1 n wesrag id yeqqimen --> %1$s • %2$s</string>
|
||||
<plurals name="poll_info_votes">
|
||||
<item quantity="one">%s wedγar</item>
|
||||
<item quantity="other">%s n yedγaren</item>
|
||||
<item quantity="one">%s n wedɣar</item>
|
||||
<item quantity="other">%s n yedɣaren</item>
|
||||
</plurals>
|
||||
<string name="poll_info_time_relative">%s id yugran</string>
|
||||
<string name="poll_info_time_absolute">ad ifak deg %s</string>
|
||||
<string name="poll_info_closed">ifuk</string>
|
||||
|
||||
<string name="poll_vote">Dγer</string>
|
||||
<string name="poll_vote">Dɣer</string>
|
||||
|
||||
<string name="poll_ended_voted">Ifuk, tura kan, yiwen wedγar t tteki-iḍ degs</string>
|
||||
<string name="poll_ended_created">Ifukk yiwen wedγar id snulfaḍ</string>
|
||||
<string name="poll_ended_voted">Ifuk, tura kan, yiwen wedɣar t tteki-iḍ degs</string>
|
||||
<string name="poll_ended_created">Ifukk yiwen wedɣar id snulfaḍ</string>
|
||||
|
||||
<plurals name="poll_timespan_days">
|
||||
<item quantity="one">%d n wass</item>
|
||||
@ -214,18 +214,18 @@
|
||||
</plurals>
|
||||
<plurals name="poll_timespan_minutes">
|
||||
<item quantity="one">%d n tasdidt</item>
|
||||
<item quantity="other">%d n tesdidin</item>
|
||||
<item quantity="other">%d n tisdidin</item>
|
||||
</plurals>
|
||||
<string name="button_continue">Kemmel</string>
|
||||
<string name="button_back">Uγal</string>
|
||||
<string name="button_back">Uɣal</string>
|
||||
<string name="failed_report">Tella-d tuccḍa deg ccetki</string>
|
||||
<string name="failed_search">Tucḍa n unadi</string>
|
||||
|
||||
<string name="create_poll_title">Assenqed</string>
|
||||
<string name="poll_duration_5_min">5 n tasditin</string>
|
||||
<string name="poll_duration_30_min">30 n tasditin</string>
|
||||
<string name="poll_duration_1_hour">1 n wesrag</string>
|
||||
<string name="poll_duration_6_hours">6 n wesragen</string>
|
||||
<string name="poll_duration_5_min">5 n tisdidin</string>
|
||||
<string name="poll_duration_30_min">30 n tisdidin</string>
|
||||
<string name="poll_duration_1_hour">1 n usrag</string>
|
||||
<string name="poll_duration_6_hours">6 n isragen</string>
|
||||
<string name="poll_duration_1_day">1 n wass</string>
|
||||
<string name="poll_duration_3_days">3 n wussan</string>
|
||||
<string name="poll_duration_7_days">7 n wussan</string>
|
||||
@ -233,30 +233,70 @@
|
||||
|
||||
<string name="title_follows">Ig ṭafaṛ</string>
|
||||
<string name="title_followers">Imeḍfaṛen</string>
|
||||
<string name="hint_search_people_list">Nadi γef medden i teṭafareḍ</string>
|
||||
<string name="hint_search_people_list">Nadi ɣef medden i teṭafareḍ</string>
|
||||
<string name="description_visiblity_private">Imeḍfaṛen</string>
|
||||
|
||||
<string name="action_links">Iseγwan</string>
|
||||
<string name="action_links">Iseɣwan</string>
|
||||
<string name="action_mentions">Tibdarin</string>
|
||||
<string name="title_mentions_dialog">Tibdarin</string>
|
||||
<string name="title_links_dialog">Iseγwan</string>
|
||||
<string name="title_links_dialog">Iseɣwan</string>
|
||||
<string name="confirmation_reported">Yettwaceyyaɛ!</string>
|
||||
<string name="status_sent">Yettwaceyyaɛ!</string>
|
||||
<string name="search_no_results">Ula d yiwen n ugmuḍ</string>
|
||||
|
||||
<string name="post_privacy_followers_only">I yimeḍfaṛen kan</string>
|
||||
|
||||
<string name="pref_status_text_size">Teγzi n weḍṛis</string>
|
||||
<string name="pref_status_text_size">Teɣzi n weḍṛis</string>
|
||||
|
||||
<string name="about_powered_by_tusky">Yettwamdemmar s Tusky</string>
|
||||
<string name="about_project_site">Asmel Web n usenfaṛ:
|
||||
\n https://tusky.app</string>
|
||||
<string name="abbreviated_hours_ago">%dasr</string>
|
||||
<string name="abbreviated_minutes_ago">%dtas</string>
|
||||
<string name="abbreviated_seconds_ago">%dtasn</string>
|
||||
<string name="abbreviated_hours_ago">%dsr</string>
|
||||
<string name="abbreviated_minutes_ago">%dtsd</string>
|
||||
<string name="abbreviated_seconds_ago">%dtsn</string>
|
||||
|
||||
<string name="compose_save_draft">Sekles amzun d arewway\?</string>
|
||||
<string name="later">Ticki</string>
|
||||
<string name="profile_badge_bot_text">Aṛubut</string>
|
||||
<string name="description_status_bookmarked">Yettwarna γer ticṛad</string>
|
||||
<string name="description_status_bookmarked">Yettwarna ɣer ticṛad</string>
|
||||
<string name="abbreviated_in_hours">deg %dsr</string>
|
||||
<string name="abbreviated_in_minutes">deg %dtsd</string>
|
||||
<string name="abbreviated_in_seconds">deg %dtsn</string>
|
||||
<plurals name="poll_timespan_seconds">
|
||||
<item quantity="one">%d n tasint</item>
|
||||
<item quantity="other">%d n tasinin</item>
|
||||
</plurals>
|
||||
|
||||
<string name="status_sensitive_media_title">Agbur amḥulfu</string>
|
||||
<string name="pref_default_media_sensitivity">Creḍ allal n teywalt amzun d amḥulfu</string>
|
||||
<string name="action_reset_schedule">Wennez tikkelt-nniḍen</string>
|
||||
<string name="error_media_upload_sending">Asali ur yeddi ara.</string>
|
||||
<string name="error_sender_account_gone">Tuccḍa deg tuzna n tijewwiqt.</string>
|
||||
|
||||
<string name="title_public_local">Adigan</string>
|
||||
<string name="title_licenses">Turagin</string>
|
||||
|
||||
<string name="status_boosted_format">Yebḍa-t %s</string>
|
||||
<string name="notification_reblog_format">%s Y·Tebḍa tijewwiqt-ik·im</string>
|
||||
<string name="notification_favourite_format">%s Y·Terna tijewwiqt-ik·im ɣer imenyafen-is</string>
|
||||
<string name="action_quick_reply">Tiririt taruradt</string>
|
||||
<string name="action_reblog">Bḍu</string>
|
||||
<string name="action_unreblog">Kkes beṭu</string>
|
||||
<string name="action_hide_reblogs">Ffer beṭuyat</string>
|
||||
<string name="action_show_reblogs">Sken-d beṭuyat</string>
|
||||
<string name="action_unmute">Ur sgugum ara</string>
|
||||
<string name="action_accept">Ddeg</string>
|
||||
<string name="action_hashtags">Ihacṭagen</string>
|
||||
<string name="action_open_reblogged_by">Sken-d beṭuyat</string>
|
||||
<string name="title_hashtags_dialog">Ihacṭagen</string>
|
||||
<string name="confirmation_unmuted">Aseqdac nni ur yettwasgugem ara tura</string>
|
||||
<string name="confirmation_domain_unmuted">%s ur yettwaffer ara</string>
|
||||
|
||||
<string name="hint_note">Assisen</string>
|
||||
<string name="label_header">Tugna n yiɣef n umaɣnu</string>
|
||||
|
||||
<string name="error_empty">Ur ilaq ara ad yili d ilem.</string>
|
||||
<string name="action_block">Cekkel</string>
|
||||
<string name="action_unblock">Kkes tacekkalt</string>
|
||||
<string name="confirmation_unblocked">Tettwakkes tacekkalt ɣef umiḍan-nni</string>
|
||||
</resources>
|
||||
|
@ -520,4 +520,6 @@
|
||||
|
||||
<string name="no_saved_status">Du har ikke lagret noen kladder.</string>
|
||||
<string name="error_audio_upload_size">Lydfiler må være mindre enn 40MB.</string>
|
||||
</resources>
|
||||
<string name="warning_scheduling_interval">Mastodon har et minimums planleggingsinterval på 5 minutter.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -491,4 +491,5 @@
|
||||
<string name="no_saved_status">Avètz pas cap de borrolhon.</string>
|
||||
<string name="no_scheduled_status">Avètz pas cap de tut planificat.</string>
|
||||
|
||||
</resources>
|
||||
<string name="warning_scheduling_interval">L’interval minimum de planificacion sus Mastodon e de 5 minutas.</string>
|
||||
</resources>
|
||||
|
@ -498,4 +498,6 @@
|
||||
<string name="no_saved_status">Nie masz żadnych szkiców.</string>
|
||||
<string name="no_scheduled_status">Nie masz żadnych zaplanowanych wpisów.</string>
|
||||
|
||||
<string name="warning_scheduling_interval">Mastodon umożliwia wysłanie minimalnie 5 minut od zaplanowania.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -486,4 +486,5 @@
|
||||
|
||||
<string name="error_audio_upload_size">Áudios devem ser menores que 40MB.</string>
|
||||
<string name="no_saved_status">Sem rascunhos.</string>
|
||||
<string name="warning_scheduling_interval">Mastodon possui um intervalo mínimo de 5 minutos para agendar.</string>
|
||||
</resources>
|
||||
|
@ -546,4 +546,13 @@
|
||||
<string name="description_status_bookmarked">Добавлено в закладки</string>
|
||||
<string name="select_list_title">Выбрать список</string>
|
||||
<string name="list">Список</string>
|
||||
</resources>
|
||||
<string name="error_audio_upload_size">Аудиофайлы должны быть меньше 40МБ.</string>
|
||||
<string name="gradient_for_media">Показывать цветные градиенты для скрытых медиа</string>
|
||||
|
||||
<string name="post_lookup_error_format">Ошибка поиска поста %s</string>
|
||||
|
||||
<string name="no_saved_status">У вас нет черновиков.</string>
|
||||
<string name="no_scheduled_status">У вас нет запланированных постов.</string>
|
||||
<string name="warning_scheduling_interval">Минимальный интервал планирования в Mastodon составляет 5 минут.</string>
|
||||
|
||||
</resources>
|
||||
|
@ -20,7 +20,7 @@
|
||||
<string name="error_media_upload_sending">Uppladdningen misslyckades.</string>
|
||||
<string name="error_sender_account_gone">Kunde inte skicka toot.</string>
|
||||
<string name="title_home">Hem</string>
|
||||
<string name="title_notifications">Notifikationer</string>
|
||||
<string name="title_notifications">Aviseringar</string>
|
||||
<string name="title_public_local">Lokalt</string>
|
||||
<string name="title_public_federated">Federerat</string>
|
||||
<string name="title_direct_messages">Direkta meddelanden</string>
|
||||
@ -158,15 +158,15 @@
|
||||
<string name="visibility_unlisted">Olistad: Visa inte i offentliga tidslinjer</string>
|
||||
<string name="visibility_private">Enbart-följare: Ses enbart av följare</string>
|
||||
<string name="visibility_direct">Direkt: Skicka endast till nämnda användare</string>
|
||||
<string name="pref_title_edit_notification_settings">Notifikationer</string>
|
||||
<string name="pref_title_notifications_enabled">Notifikationer</string>
|
||||
<string name="pref_title_edit_notification_settings">Aviseringar</string>
|
||||
<string name="pref_title_notifications_enabled">Aviseringar</string>
|
||||
<string name="pref_title_notification_alerts">Alarm</string>
|
||||
<string name="pref_title_notification_alert_sound">Meddela med ljud</string>
|
||||
<string name="pref_title_notification_alert_vibrate">Meddela med vibration</string>
|
||||
<string name="pref_title_notification_alert_light">Notifieringar med LED</string>
|
||||
<string name="pref_title_notification_filters">Meddela mig när</string>
|
||||
<string name="pref_title_notification_filter_mentions">omnämnd</string>
|
||||
<string name="pref_title_notification_filter_follows">följande</string>
|
||||
<string name="pref_title_notification_filter_follows">nya följare</string>
|
||||
<string name="pref_title_notification_filter_reblogs">mina inlägg är knuffade</string>
|
||||
<string name="pref_title_notification_filter_favourites">mina inlägg är favoriserade</string>
|
||||
<string name="pref_title_appearance_settings">Utseende</string>
|
||||
@ -177,7 +177,7 @@
|
||||
<string name="app_theme_light">Ljust</string>
|
||||
<string name="app_theme_black">Svart</string>
|
||||
<string name="app_theme_auto">Automatiskt vid solnedgång</string>
|
||||
<string name="app_theme_system">Använd systemdesign</string>
|
||||
<string name="app_theme_system">Använd system-tema</string>
|
||||
<string name="pref_title_browser_settings">Webbläsare</string>
|
||||
<string name="pref_title_custom_tabs">Använd Chrome-anpassade flikar</string>
|
||||
<string name="pref_title_hide_follow_button">Dölj skriv-knappen vid skrollning</string>
|
||||
@ -206,13 +206,13 @@
|
||||
<string name="status_text_size_large">Stor</string>
|
||||
<string name="status_text_size_largest">Största</string>
|
||||
<string name="notification_mention_name">Nya omnämnanden</string>
|
||||
<string name="notification_mention_descriptions">Notifieringar om nya omnämnanden</string>
|
||||
<string name="notification_mention_descriptions">Aviseringar om nya omnämnanden</string>
|
||||
<string name="notification_follow_name">Nya följare</string>
|
||||
<string name="notification_follow_description">Notifieringar om nya följare</string>
|
||||
<string name="notification_follow_description">Aviseringar på nya följare</string>
|
||||
<string name="notification_boost_name">Knuffar</string>
|
||||
<string name="notification_boost_description">Notifieringar när dina toots blir knuffade</string>
|
||||
<string name="notification_boost_description">Aviseringar när dina toots blir knuffade</string>
|
||||
<string name="notification_favourite_name">Favoriter</string>
|
||||
<string name="notification_favourite_description">Notifieringar när dina toots blir markerade som favoriter</string>
|
||||
<string name="notification_favourite_description">Aviseringar när dina toots blir markerade som favoriter</string>
|
||||
<string name="notification_mention_format">%s omnämnde dig</string>
|
||||
<string name="notification_summary_large">%1$s, %2$s, %3$s och %4$d andra</string>
|
||||
<string name="notification_summary_medium">%1$s, %2$s, och %3$s</string>
|
||||
@ -239,7 +239,7 @@
|
||||
<string name="status_share_link">Dela länk till toot</string>
|
||||
<string name="status_media_images">Bilder</string>
|
||||
<string name="status_media_video">Video</string>
|
||||
<string name="state_follow_requested">Följarförfrågad</string>
|
||||
<string name="state_follow_requested">Följarförfrågan</string>
|
||||
<!--These are for timestamps on statuses. For example: "16s" or "2d"-->
|
||||
<string name="abbreviated_in_years">om %dy</string>
|
||||
<string name="abbreviated_in_days">om %dd</string>
|
||||
@ -272,9 +272,9 @@
|
||||
<string name="error_rename_list">Kunde inte byta namn på lista</string>
|
||||
<string name="error_delete_list">Kunde inte radera lista</string>
|
||||
<string name="action_create_list">Skapa en lista</string>
|
||||
<string name="action_rename_list">Byt namn</string>
|
||||
<string name="action_delete_list">Ta bort</string>
|
||||
<string name="action_edit_list">Ändra</string>
|
||||
<string name="action_rename_list">Byt namn på listan</string>
|
||||
<string name="action_delete_list">Ta bort listan</string>
|
||||
<string name="action_edit_list">Redigera lista</string>
|
||||
<string name="hint_search_people_list">Sök efter personer du följer</string>
|
||||
<string name="action_add_to_list">Lägg till konto i listan</string>
|
||||
<string name="action_remove_from_list">Ta bort kontot från listan</string>
|
||||
@ -287,7 +287,7 @@
|
||||
<string name="lock_account_label_description">Kräver att du manuellt godkänner följare</string>
|
||||
<string name="compose_save_draft">Spara utkast?</string>
|
||||
<string name="send_toot_notification_title">Skickar toot…</string>
|
||||
<string name="send_toot_notification_error_title">Fel vid sändning av toot</string>
|
||||
<string name="send_toot_notification_error_title">Kunde inte skicka toot</string>
|
||||
<string name="send_toot_notification_channel_name">Skickar toot</string>
|
||||
<string name="send_toot_notification_cancel_title">Sändning avbruten</string>
|
||||
<string name="send_toot_notification_saved_content">En kopia av tooten har sparats i dina utkast</string>
|
||||
@ -298,14 +298,14 @@
|
||||
<string name="system_default">Systemstandard</string>
|
||||
<string name="download_fonts">Du behöver ladda ned dessa emojis först</string>
|
||||
<string name="performing_lookup_title">Utför sökning…</string>
|
||||
<string name="expand_collapse_all_statuses">Expandera/Dölj alla status</string>
|
||||
<string name="expand_collapse_all_statuses">Expandera/Dölj alla statusar</string>
|
||||
<string name="action_open_toot">Öppna toot</string>
|
||||
<string name="restart_required">Omstart av appen krävs</string>
|
||||
<string name="restart_emoji">Du måste starta om Yuito för att tillämpa ändringarna</string>
|
||||
<string name="later">Senare</string>
|
||||
<string name="restart">Starta om</string>
|
||||
<string name="caption_systememoji">Standard-emojis för din enhet</string>
|
||||
<string name="caption_blobmoji">Emojis baserade på The Blob emojis kända från Android 4.4–7.1</string>
|
||||
<string name="caption_blobmoji">Emojis baserade på The Blob emojis från Android 4.4–7.1</string>
|
||||
<string name="caption_twemoji">Mastodon\'s standard emojis</string>
|
||||
<string name="download_failed">Nedladdning misslyckad</string>
|
||||
<string name="profile_badge_bot_text">Robot</string>
|
||||
@ -373,9 +373,9 @@
|
||||
|
||||
<string name="pref_title_bot_overlay">Visa robotindikator</string>
|
||||
|
||||
<string name="notification_clear_text">Är du säker på att du vill rensa dina notifieringar permanent\?</string>
|
||||
<string name="notification_clear_text">Är du säker på att du vill rensa dina aviseringar permanent\?</string>
|
||||
|
||||
<string name="action_delete_and_redraft">Radera och skriv nytt</string>
|
||||
<string name="action_delete_and_redraft">Radera och skriv på nytt</string>
|
||||
<string name="dialog_redraft_toot_warning">Radera och skriv ny toot\?</string>
|
||||
|
||||
<string name="poll_info_format"> <!-- 15 röster • 1 timme kvar --> %1$s • %2$s</string>
|
||||
@ -384,15 +384,15 @@
|
||||
<item quantity="other">%s röster</item>
|
||||
</plurals>
|
||||
<string name="poll_info_time_relative">%s kvar</string>
|
||||
<string name="poll_info_time_absolute">avslutas %s</string>
|
||||
<string name="poll_info_time_absolute">avslutas vid %s</string>
|
||||
<string name="poll_info_closed">stängd</string>
|
||||
|
||||
<string name="poll_vote">Rösta</string>
|
||||
|
||||
|
||||
<string name="pref_title_notification_filter_poll">omröstning är avslutad</string>
|
||||
<string name="pref_title_notification_filter_poll">omröstningar har avslutats</string>
|
||||
<string name="notification_poll_name">Omröstningar</string>
|
||||
<string name="notification_poll_description">Notifieringar när omröstningar har avslutats</string>
|
||||
<string name="notification_poll_description">Aviseringar när omröstningar har avslutats</string>
|
||||
|
||||
|
||||
<string name="poll_ended_voted">En omröstning där du har röstat är avslutad</string>
|
||||
@ -424,9 +424,9 @@
|
||||
<string name="title_domain_mutes">Dolda domäner</string>
|
||||
<string name="action_view_domain_mutes">Dolda domäner</string>
|
||||
<string name="action_mute_domain">Tysta %s</string>
|
||||
<string name="confirmation_domain_unmuted">%s inte tystnad längre</string>
|
||||
<string name="confirmation_domain_unmuted">%s inte tystad längre</string>
|
||||
|
||||
<string name="mute_domain_warning">Är du säker på att du vill blockera allt från %s\? Du kommer inte kunna se något innehåll från denna domän i publika tidslinje eller i dina notifieringar. Dina följare på domänen kommer inte att bli borttagna.</string>
|
||||
<string name="mute_domain_warning">Är du säker på att du vill blockera allt från %s\? Du kommer inte kunna se något innehåll från denna domän i publika tidslinjer eller i dina notifieringar. Dina följare på domänen kommer inte att bli borttagna.</string>
|
||||
<string name="mute_domain_warning_dialog_ok">Dölj hela domänen</string>
|
||||
|
||||
<string name="caption_notoemoji">Google\'s nuvarande emojis</string>
|
||||
@ -443,7 +443,7 @@
|
||||
|
||||
<string name="pref_title_show_notifications_filter">Visa notifikationsfilter</string>
|
||||
<string name="filter_dialog_whole_word">Helt ord</string>
|
||||
<string name="filter_dialog_whole_word_description">När nyckelordet eller frasen är alfanumerisk enbart, blir den enbart appliceras om den matchar hela ordet</string>
|
||||
<string name="filter_dialog_whole_word_description">När nyckelordet eller frasen enbart är alfanumerisk, appliceras den om den matchar hela ordet</string>
|
||||
<string name="pref_title_alway_open_spoiler">Expandera alltid toots med innehållsvarningar</string>
|
||||
<string name="title_accounts">Konton</string>
|
||||
<string name="failed_search">Sökning misslyckades</string>
|
||||
@ -482,4 +482,5 @@
|
||||
|
||||
<string name="error_audio_upload_size">Ljudfiler måste vara mindre än 40MB.</string>
|
||||
<string name="no_saved_status">Du har inga utkast.</string>
|
||||
<string name="warning_scheduling_interval">Mastodon har ett minimalt schemaläggningsintervall på 5 minuter.</string>
|
||||
</resources>
|
||||
|
@ -161,7 +161,7 @@
|
||||
|
||||
<string name="login_connection">正在連線…</string>
|
||||
|
||||
<string name="dialog_whats_an_instance">請輸入你帳號所在的 Mastodon 站點的域名或地址</string>
|
||||
<string name="dialog_whats_an_instance">"請輸入你帳號所在的 Mastodon 站點的域名或地址 "</string>
|
||||
|
||||
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
||||
|
||||
<string name="login_connection">正在連線…</string>
|
||||
|
||||
<string name="dialog_whats_an_instance">請輸入你帳號所在的 Mastodon 站點的域名或地址</string>
|
||||
<string name="dialog_whats_an_instance">"請輸入你帳號所在的 Mastodon 站點的域名或地址 "</string>
|
||||
|
||||
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
||||
|
||||
<string name="login_connection">正在連線…</string>
|
||||
|
||||
<string name="dialog_whats_an_instance">請輸入你帳號所在的 Mastodon 站點的域名或地址</string>
|
||||
<string name="dialog_whats_an_instance">"請輸入你帳號所在的 Mastodon 站點的域名或地址 "</string>
|
||||
|
||||
|
||||
<string name="dialog_title_finishing_media_upload">正在完成上傳…</string>
|
||||
|
@ -22,4 +22,5 @@
|
||||
<item name="action_open_reblogger" type="id" />
|
||||
<item name="action_open_reblogged_by" type="id" />
|
||||
<item name="action_open_faved_by" type="id" />
|
||||
<item name="action_more" type="id" />
|
||||
</resources>
|
@ -7,7 +7,6 @@
|
||||
<dimen name="compose_media_preview_margin">8dp</dimen>
|
||||
<dimen name="compose_media_preview_margin_bottom">0dp</dimen>
|
||||
<dimen name="compose_media_preview_size">120dp</dimen>
|
||||
<dimen name="compose_options_margin">8dp</dimen>
|
||||
<dimen name="account_avatar_margin">14dp</dimen>
|
||||
<dimen name="tab_page_margin">16dp</dimen>
|
||||
<dimen name="status_line_margin_start">36dp</dimen>
|
||||
|
@ -65,6 +65,7 @@
|
||||
<string name="notification_reblog_format">%s boosted your toot</string>
|
||||
<string name="notification_favourite_format">%s favorited your toot</string>
|
||||
<string name="notification_follow_format">%s followed you</string>
|
||||
<string name="notification_follow_request_format">%s requested to follow you</string>
|
||||
|
||||
<string name="report_username_format">Report @%s</string>
|
||||
<string name="report_comment_hint">Additional comments?</string>
|
||||
@ -113,6 +114,8 @@
|
||||
<string name="action_mute">Mute</string>
|
||||
<string name="action_unmute">Unmute</string>
|
||||
<string name="action_mute_domain">Mute %s</string>
|
||||
<string name="action_mute_conversation">Mute conversation</string>
|
||||
<string name="action_unmute_conversation">Unmute conversation</string>
|
||||
<string name="action_mention">Mention</string>
|
||||
<string name="action_hide_media">Hide media</string>
|
||||
<string name="action_open_drawer">Open drawer</string>
|
||||
@ -205,6 +208,8 @@
|
||||
<string name="dialog_redraft_toot_warning">Delete and re-draft this toot?</string>
|
||||
<string name="mute_domain_warning">Are you sure you want to block all of %s? You will not see content from that domain in any public timelines or in your notifications. Your followers from that domain will be removed.</string>
|
||||
<string name="mute_domain_warning_dialog_ok">Hide entire domain</string>
|
||||
<string name="dialog_block_warning">Block @%s?</string>
|
||||
<string name="dialog_mute_warning">Mute @%s?</string>
|
||||
|
||||
<string name="visibility_public">Public: Post to public timelines</string>
|
||||
<string name="visibility_unlisted">Unlisted: Do not show in public timelines</string>
|
||||
@ -221,6 +226,7 @@
|
||||
<string name="pref_title_notification_filters">Notify me when</string>
|
||||
<string name="pref_title_notification_filter_mentions">mentioned</string>
|
||||
<string name="pref_title_notification_filter_follows">followed</string>
|
||||
<string name="pref_title_notification_filter_follow_requests">follow requested</string>
|
||||
<string name="pref_title_notification_filter_reblogs">my posts are boosted</string>
|
||||
<string name="pref_title_notification_filter_favourites">my posts are favorited</string>
|
||||
<string name="pref_title_notification_filter_poll">polls have ended</string>
|
||||
@ -284,6 +290,8 @@
|
||||
<string name="notification_mention_descriptions">Notifications about new mentions</string>
|
||||
<string name="notification_follow_name">New Followers</string>
|
||||
<string name="notification_follow_description">Notifications about new followers</string>
|
||||
<string name="notification_follow_request_name">Follow Requests</string>
|
||||
<string name="notification_follow_request_description">Notifications about follow requests</string>
|
||||
<string name="notification_boost_name">Boosts</string>
|
||||
<string name="notification_boost_description">Notifications when your toots get boosted</string>
|
||||
<string name="notification_favourite_name">Favorites</string>
|
||||
@ -516,6 +524,10 @@
|
||||
<item quantity="one">%s vote</item>
|
||||
<item quantity="other">%s votes</item>
|
||||
</plurals>
|
||||
<plurals name="poll_info_people">
|
||||
<item quantity="one">%s person</item>
|
||||
<item quantity="other">%s people</item>
|
||||
</plurals>
|
||||
<string name="poll_info_time_relative">%s left</string>
|
||||
<string name="poll_info_time_absolute">ends at %s</string>
|
||||
<string name="poll_info_closed">closed</string>
|
||||
@ -576,5 +588,7 @@
|
||||
<string name="no_saved_status">You don\'t have any drafts.</string>
|
||||
<string name="no_scheduled_status">You don\'t have any scheduled statuses.</string>
|
||||
<string name="warning_scheduling_interval">Mastodon has a minimum scheduling interval of 5 minutes.</string>
|
||||
<string name="pref_title_show_cards_in_timelines">Show link previews in timelines</string>
|
||||
<string name="pref_title_confirm_reblogs">Show confirmation dialog before boosting</string>
|
||||
|
||||
</resources>
|
||||
|
@ -27,6 +27,12 @@
|
||||
android:title="@string/pref_title_notification_filter_follows"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="notificationFilterFollowRequests"
|
||||
android:title="@string/pref_title_notification_filter_follow_requests"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="notificationFilterReblogs"
|
||||
|
@ -72,6 +72,18 @@
|
||||
android:title="@string/pref_title_show_notifications_filter"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="showCardsInTimelines"
|
||||
android:title="@string/pref_title_show_cards_in_timelines"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="confirmReblogs"
|
||||
android:title="@string/pref_title_confirm_reblogs"
|
||||
app:singleLineTitle="false" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/pref_title_limited_bandwidth_settings">
|
||||
|
@ -88,6 +88,7 @@ class BottomSheetActivityTest {
|
||||
arrayOf(),
|
||||
null,
|
||||
pinned = false,
|
||||
muted = false,
|
||||
poll = null,
|
||||
card = null
|
||||
)
|
||||
|
@ -68,6 +68,7 @@ class ComposeActivityTest {
|
||||
notificationsEnabled = true,
|
||||
notificationsMentioned = true,
|
||||
notificationsFollowed = true,
|
||||
notificationsFollowRequested = false,
|
||||
notificationsReblogged = true,
|
||||
notificationsFavorited = true,
|
||||
notificationSound = true,
|
||||
|
@ -11,6 +11,7 @@ import com.keylesspalace.tusky.fragment.SFragment
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import okhttp3.Request
|
||||
import okio.Timeout
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
@ -99,6 +100,10 @@ class FilterTest {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun timeout(): Timeout {
|
||||
throw Error("not implemented")
|
||||
}
|
||||
})
|
||||
|
||||
activity.mastodonApi = apiMock
|
||||
@ -214,6 +219,7 @@ class FilterTest {
|
||||
mentions = emptyArray(),
|
||||
application = null,
|
||||
pinned = false,
|
||||
muted = false,
|
||||
poll = if (pollOptions != null) {
|
||||
Poll(
|
||||
id = "1234",
|
||||
@ -221,6 +227,7 @@ class FilterTest {
|
||||
expired = false,
|
||||
multiple = false,
|
||||
votesCount = 0,
|
||||
votersCount = 0,
|
||||
options = pollOptions.map {
|
||||
PollOption(it, 0)
|
||||
},
|
||||
|
@ -18,13 +18,9 @@ package com.keylesspalace.tusky
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.util.Log
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import com.keylesspalace.tusky.util.LocaleManager
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import de.c1710.filemojicompat.FileEmojiCompatConfig
|
||||
import javax.inject.Inject
|
||||
|
||||
// override TuskyApplication for Robolectric tests, only initialize the necessary stuff
|
||||
class TuskyApplication : Application() {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.keylesspalace.tusky.fragment
|
||||
|
||||
import android.text.Spanned
|
||||
import android.text.SpannableString
|
||||
import android.text.SpannedString
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.google.gson.Gson
|
||||
import com.keylesspalace.tusky.SpanUtilsTest
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
@ -12,7 +14,6 @@ import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.repository.*
|
||||
import com.keylesspalace.tusky.util.Either
|
||||
import com.keylesspalace.tusky.util.HtmlConverter
|
||||
import com.nhaarman.mockitokotlin2.isNull
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
@ -24,14 +25,18 @@ import io.reactivex.schedulers.TestScheduler
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.any
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.robolectric.annotation.Config
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@Config(sdk = [28])
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TimelineRepositoryTest {
|
||||
@Mock
|
||||
lateinit var timelineDao: TimelineDao
|
||||
@ -56,15 +61,6 @@ class TimelineRepositoryTest {
|
||||
domain = "domain.com",
|
||||
isActive = true
|
||||
)
|
||||
private val htmlConverter = object : HtmlConverter {
|
||||
override fun fromHtml(html: String): Spanned {
|
||||
return SpanUtilsTest.FakeSpannable(html)
|
||||
}
|
||||
|
||||
override fun toHtml(text: Spanned): String {
|
||||
return text.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
@ -74,8 +70,7 @@ class TimelineRepositoryTest {
|
||||
gson = Gson()
|
||||
testScheduler = TestScheduler()
|
||||
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
|
||||
subject = TimelineRepositoryImpl(timelineDao, mastodonApi, accountManager, gson,
|
||||
htmlConverter)
|
||||
subject = TimelineRepositoryImpl(timelineDao, mastodonApi, accountManager, gson)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -97,7 +92,7 @@ class TimelineRepositoryTest {
|
||||
verify(timelineDao).insertStatusIfNotThere(Placeholder("1").toEntity(account.id))
|
||||
for (status in statuses) {
|
||||
verify(timelineDao).insertInTransaction(
|
||||
status.toEntity(account.id, htmlConverter, gson),
|
||||
status.toEntity(account.id, gson),
|
||||
status.account.toEntity(account.id, gson),
|
||||
null
|
||||
)
|
||||
@ -129,7 +124,7 @@ class TimelineRepositoryTest {
|
||||
// We assume for now that overlapped one is inserted but it's not that important
|
||||
for (status in response) {
|
||||
verify(timelineDao).insertInTransaction(
|
||||
status.toEntity(account.id, htmlConverter, gson),
|
||||
status.toEntity(account.id, gson),
|
||||
status.account.toEntity(account.id, gson),
|
||||
null
|
||||
)
|
||||
@ -159,7 +154,7 @@ class TimelineRepositoryTest {
|
||||
verify(timelineDao).deleteRange(account.id, response.last().id, response.first().id)
|
||||
for (status in response) {
|
||||
verify(timelineDao).insertInTransaction(
|
||||
status.toEntity(account.id, htmlConverter, gson),
|
||||
status.toEntity(account.id, gson),
|
||||
status.account.toEntity(account.id, gson),
|
||||
null
|
||||
)
|
||||
@ -201,7 +196,7 @@ class TimelineRepositoryTest {
|
||||
// We assume for now that overlapped one is inserted but it's not that important
|
||||
for (status in response) {
|
||||
verify(timelineDao).insertInTransaction(
|
||||
status.toEntity(account.id, htmlConverter, gson),
|
||||
status.toEntity(account.id, gson),
|
||||
status.account.toEntity(account.id, gson),
|
||||
null
|
||||
)
|
||||
@ -246,7 +241,7 @@ class TimelineRepositoryTest {
|
||||
|
||||
for (status in response) {
|
||||
verify(timelineDao).insertInTransaction(
|
||||
status.toEntity(account.id, htmlConverter, gson),
|
||||
status.toEntity(account.id, gson),
|
||||
status.account.toEntity(account.id, gson),
|
||||
null
|
||||
)
|
||||
@ -263,7 +258,7 @@ class TimelineRepositoryTest {
|
||||
val status = makeStatus("2")
|
||||
val dbStatus = makeStatus("1")
|
||||
val dbResult = TimelineStatusWithAccount()
|
||||
dbResult.status = dbStatus.toEntity(account.id, htmlConverter, gson)
|
||||
dbResult.status = dbStatus.toEntity(account.id, gson)
|
||||
dbResult.account = status.account.toEntity(account.id, gson)
|
||||
|
||||
whenever(mastodonApi.homeTimelineSingle(any(), any(), any()))
|
||||
@ -297,7 +292,7 @@ class TimelineRepositoryTest {
|
||||
return Status(
|
||||
id = id,
|
||||
account = account,
|
||||
content = SpanUtilsTest.FakeSpannable("hello$id"),
|
||||
content = SpannableString("hello$id"),
|
||||
createdAt = Date(),
|
||||
emojis = listOf(),
|
||||
reblogsCount = 3,
|
||||
@ -314,6 +309,7 @@ class TimelineRepositoryTest {
|
||||
inReplyToAccountId = null,
|
||||
inReplyToId = null,
|
||||
pinned = false,
|
||||
muted = false,
|
||||
reblog = null,
|
||||
url = "http://example.com/statuses/$id",
|
||||
poll = null,
|
||||
@ -328,7 +324,7 @@ class TimelineRepositoryTest {
|
||||
localUsername = "test$id",
|
||||
username = "test$id@example.com",
|
||||
displayName = "Example Account $id",
|
||||
note = SpanUtilsTest.FakeSpannable("Note! $id"),
|
||||
note = SpannableString("Note! $id"),
|
||||
url = "https://example.com/@test$id",
|
||||
avatar = "avatar$id",
|
||||
header = "Header$id",
|
||||
|
@ -1,11 +1,11 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.61'
|
||||
ext.kotlin_version = '1.3.71'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Un client per a diversos comptes per a la xarxa social Mastodont
|
||||
Un client multicomptes per a la xarxa social Mastodont
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user