Implement custom hashtag feed with ViewModel
This commit is contained in:
parent
5a10a2bae4
commit
4a2b266f01
|
@ -0,0 +1,991 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 9,
|
||||
"identityHash": "5ee0e8fbaef28650cbea6670e24e08bb",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "instances",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uri` TEXT NOT NULL, `title` TEXT NOT NULL, `maxStatusChars` INTEGER NOT NULL, `maxPhotoSize` INTEGER NOT NULL, `maxVideoSize` INTEGER NOT NULL, `albumLimit` INTEGER NOT NULL, `videoEnabled` INTEGER NOT NULL, `pixelfed` INTEGER NOT NULL, PRIMARY KEY(`uri`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uri",
|
||||
"columnName": "uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxStatusChars",
|
||||
"columnName": "maxStatusChars",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxPhotoSize",
|
||||
"columnName": "maxPhotoSize",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "maxVideoSize",
|
||||
"columnName": "maxVideoSize",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "albumLimit",
|
||||
"columnName": "albumLimit",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "videoEnabled",
|
||||
"columnName": "videoEnabled",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "pixelfed",
|
||||
"columnName": "pixelfed",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"uri"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "users",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, `username` TEXT NOT NULL, `display_name` TEXT NOT NULL, `avatar_static` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT, `clientId` TEXT NOT NULL, `clientSecret` TEXT NOT NULL, PRIMARY KEY(`user_id`, `instance_uri`), FOREIGN KEY(`instance_uri`) REFERENCES `instances`(`uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "username",
|
||||
"columnName": "username",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "display_name",
|
||||
"columnName": "display_name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "avatar_static",
|
||||
"columnName": "avatar_static",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isActive",
|
||||
"columnName": "isActive",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "accessToken",
|
||||
"columnName": "accessToken",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "refreshToken",
|
||||
"columnName": "refreshToken",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "clientId",
|
||||
"columnName": "clientId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "clientSecret",
|
||||
"columnName": "clientSecret",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_users_instance_uri",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"instance_uri"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_users_instance_uri` ON `${TABLE_NAME}` (`instance_uri`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "instances",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "homePosts",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, `id` TEXT NOT NULL, `uri` TEXT, `created_at` TEXT, `account` TEXT, `content` TEXT, `visibility` TEXT, `sensitive` INTEGER, `spoiler_text` TEXT, `media_attachments` TEXT, `application` TEXT, `mentions` TEXT, `tags` TEXT, `emojis` TEXT, `reblogs_count` INTEGER, `favourites_count` INTEGER, `replies_count` INTEGER, `url` TEXT, `in_reply_to_id` TEXT, `in_reply_to_account` TEXT, `reblog` TEXT, `poll` TEXT, `card` TEXT, `language` TEXT, `text` TEXT, `favourited` INTEGER, `reblogged` INTEGER, `muted` INTEGER, `bookmarked` INTEGER, `pinned` INTEGER, PRIMARY KEY(`id`, `user_id`, `instance_uri`), FOREIGN KEY(`user_id`, `instance_uri`) REFERENCES `users`(`user_id`, `instance_uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "uri",
|
||||
"columnName": "uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created_at",
|
||||
"columnName": "created_at",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "account",
|
||||
"columnName": "account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "sensitive",
|
||||
"columnName": "sensitive",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "spoiler_text",
|
||||
"columnName": "spoiler_text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "media_attachments",
|
||||
"columnName": "media_attachments",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "application",
|
||||
"columnName": "application",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "mentions",
|
||||
"columnName": "mentions",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "tags",
|
||||
"columnName": "tags",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "emojis",
|
||||
"columnName": "emojis",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reblogs_count",
|
||||
"columnName": "reblogs_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "favourites_count",
|
||||
"columnName": "favourites_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "replies_count",
|
||||
"columnName": "replies_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "in_reply_to_id",
|
||||
"columnName": "in_reply_to_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "in_reply_to_account",
|
||||
"columnName": "in_reply_to_account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reblog",
|
||||
"columnName": "reblog",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "poll",
|
||||
"columnName": "poll",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "card",
|
||||
"columnName": "card",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "language",
|
||||
"columnName": "language",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "favourited",
|
||||
"columnName": "favourited",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reblogged",
|
||||
"columnName": "reblogged",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "muted",
|
||||
"columnName": "muted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "bookmarked",
|
||||
"columnName": "bookmarked",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "pinned",
|
||||
"columnName": "pinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id",
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_homePosts_user_id_instance_uri",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_homePosts_user_id_instance_uri` ON `${TABLE_NAME}` (`user_id`, `instance_uri`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "users",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "publicPosts",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, `id` TEXT NOT NULL, `uri` TEXT, `created_at` TEXT, `account` TEXT, `content` TEXT, `visibility` TEXT, `sensitive` INTEGER, `spoiler_text` TEXT, `media_attachments` TEXT, `application` TEXT, `mentions` TEXT, `tags` TEXT, `emojis` TEXT, `reblogs_count` INTEGER, `favourites_count` INTEGER, `replies_count` INTEGER, `url` TEXT, `in_reply_to_id` TEXT, `in_reply_to_account` TEXT, `reblog` TEXT, `poll` TEXT, `card` TEXT, `language` TEXT, `text` TEXT, `favourited` INTEGER, `reblogged` INTEGER, `muted` INTEGER, `bookmarked` INTEGER, `pinned` INTEGER, PRIMARY KEY(`id`, `user_id`, `instance_uri`), FOREIGN KEY(`user_id`, `instance_uri`) REFERENCES `users`(`user_id`, `instance_uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "uri",
|
||||
"columnName": "uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created_at",
|
||||
"columnName": "created_at",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "account",
|
||||
"columnName": "account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "visibility",
|
||||
"columnName": "visibility",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "sensitive",
|
||||
"columnName": "sensitive",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "spoiler_text",
|
||||
"columnName": "spoiler_text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "media_attachments",
|
||||
"columnName": "media_attachments",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "application",
|
||||
"columnName": "application",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "mentions",
|
||||
"columnName": "mentions",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "tags",
|
||||
"columnName": "tags",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "emojis",
|
||||
"columnName": "emojis",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reblogs_count",
|
||||
"columnName": "reblogs_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "favourites_count",
|
||||
"columnName": "favourites_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "replies_count",
|
||||
"columnName": "replies_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "url",
|
||||
"columnName": "url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "in_reply_to_id",
|
||||
"columnName": "in_reply_to_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "in_reply_to_account",
|
||||
"columnName": "in_reply_to_account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reblog",
|
||||
"columnName": "reblog",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "poll",
|
||||
"columnName": "poll",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "card",
|
||||
"columnName": "card",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "language",
|
||||
"columnName": "language",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "favourited",
|
||||
"columnName": "favourited",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reblogged",
|
||||
"columnName": "reblogged",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "muted",
|
||||
"columnName": "muted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "bookmarked",
|
||||
"columnName": "bookmarked",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "pinned",
|
||||
"columnName": "pinned",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id",
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_publicPosts_user_id_instance_uri",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_publicPosts_user_id_instance_uri` ON `${TABLE_NAME}` (`user_id`, `instance_uri`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "users",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "notifications",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` TEXT, `created_at` TEXT, `account` TEXT, `status` TEXT, `user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, PRIMARY KEY(`id`, `user_id`, `instance_uri`), FOREIGN KEY(`user_id`, `instance_uri`) REFERENCES `users`(`user_id`, `instance_uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created_at",
|
||||
"columnName": "created_at",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "account",
|
||||
"columnName": "account",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "status",
|
||||
"columnName": "status",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id",
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_notifications_user_id_instance_uri",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_notifications_user_id_instance_uri` ON `${TABLE_NAME}` (`user_id`, `instance_uri`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "users",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "tabsChecked",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`index` INTEGER NOT NULL, `user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, `tab` TEXT NOT NULL, `checked` INTEGER NOT NULL, `filter` TEXT, PRIMARY KEY(`index`, `user_id`, `instance_uri`), FOREIGN KEY(`user_id`, `instance_uri`) REFERENCES `users`(`user_id`, `instance_uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "index",
|
||||
"columnName": "index",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tab",
|
||||
"columnName": "tab",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "checked",
|
||||
"columnName": "checked",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "filter",
|
||||
"columnName": "filter",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"index",
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_tabsChecked_user_id_instance_uri",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_tabsChecked_user_id_instance_uri` ON `${TABLE_NAME}` (`user_id`, `instance_uri`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "users",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "directMessages",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `unread` INTEGER, `accounts` TEXT, `last_status` TEXT, `user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, PRIMARY KEY(`id`, `user_id`, `instance_uri`), FOREIGN KEY(`user_id`, `instance_uri`) REFERENCES `users`(`user_id`, `instance_uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unread",
|
||||
"columnName": "unread",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "accounts",
|
||||
"columnName": "accounts",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "last_status",
|
||||
"columnName": "last_status",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id",
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_directMessages_user_id_instance_uri",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_directMessages_user_id_instance_uri` ON `${TABLE_NAME}` (`user_id`, `instance_uri`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "users",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "directMessagesThreads",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT, `hidden` INTEGER, `isAuthor` INTEGER, `type` TEXT, `text` TEXT, `media` TEXT, `carousel` TEXT, `created_at` TEXT, `timeAgo` TEXT, `reportId` TEXT, `conversationsId` TEXT NOT NULL, `user_id` TEXT NOT NULL, `instance_uri` TEXT NOT NULL, PRIMARY KEY(`id`, `conversationsId`, `user_id`, `instance_uri`), FOREIGN KEY(`user_id`, `instance_uri`) REFERENCES `users`(`user_id`, `instance_uri`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "hidden",
|
||||
"columnName": "hidden",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "isAuthor",
|
||||
"columnName": "isAuthor",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "text",
|
||||
"columnName": "text",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "media",
|
||||
"columnName": "media",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "carousel",
|
||||
"columnName": "carousel",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created_at",
|
||||
"columnName": "created_at",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "timeAgo",
|
||||
"columnName": "timeAgo",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "reportId",
|
||||
"columnName": "reportId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "conversationsId",
|
||||
"columnName": "conversationsId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "user_id",
|
||||
"columnName": "user_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "instance_uri",
|
||||
"columnName": "instance_uri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": false,
|
||||
"columnNames": [
|
||||
"id",
|
||||
"conversationsId",
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_directMessagesThreads_user_id_instance_uri_conversationsId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
"instance_uri",
|
||||
"conversationsId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_directMessagesThreads_user_id_instance_uri_conversationsId` ON `${TABLE_NAME}` (`user_id`, `instance_uri`, `conversationsId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "users",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "CASCADE",
|
||||
"columns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"user_id",
|
||||
"instance_uri"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"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, '5ee0e8fbaef28650cbea6670e24e08bb')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -62,12 +62,14 @@ import org.pixeldroid.app.posts.NestedScrollableHost
|
|||
import org.pixeldroid.app.posts.feeds.cachedFeeds.CachedFeedFragment
|
||||
import org.pixeldroid.app.posts.feeds.cachedFeeds.notifications.NotificationsFragment
|
||||
import org.pixeldroid.app.posts.feeds.cachedFeeds.postFeeds.PostFeedFragment
|
||||
import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedPostsFragment
|
||||
import org.pixeldroid.app.profile.ProfileActivity
|
||||
import org.pixeldroid.app.searchDiscover.SearchDiscoverFragment
|
||||
import org.pixeldroid.app.settings.SettingsActivity
|
||||
import org.pixeldroid.app.utils.BaseActivity
|
||||
import org.pixeldroid.app.utils.Tab
|
||||
import org.pixeldroid.app.utils.api.objects.Notification
|
||||
import org.pixeldroid.app.utils.api.objects.Tag
|
||||
import org.pixeldroid.app.utils.db.entities.HomeStatusDatabaseEntity
|
||||
import org.pixeldroid.app.utils.db.entities.PublicFeedStatusDatabaseEntity
|
||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
|
@ -476,9 +478,17 @@ class MainActivity : BaseActivity() {
|
|||
arguments = Bundle().apply { putBoolean("home", false) }
|
||||
}
|
||||
} }
|
||||
Tab.DIRECT_MESSAGES -> {{
|
||||
Tab.DIRECT_MESSAGES -> { {
|
||||
DirectMessagesFragment()
|
||||
}}
|
||||
} }
|
||||
Tab.HASHTAG_FEED -> { {
|
||||
UncachedPostsFragment()
|
||||
.apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(Tag.HASHTAG_TAG, this@getFragment.filter)
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,9 +507,25 @@ class MainActivity : BaseActivity() {
|
|||
if(tabs.contains(Tab.DIRECT_MESSAGES)) removeGroup(R.id.dmNavigationGroup)
|
||||
}
|
||||
|
||||
tabs.zip(pageIds).forEach { (tabId, pageId) ->
|
||||
with(bottomNavigationMenu?.add(R.id.tabsId, pageId, 1, tabId.toLanguageString(baseContext))) {
|
||||
val tabIcon = tabId.getDrawable(applicationContext)
|
||||
val user = db.userDao().getActiveUser()!!
|
||||
|
||||
// Get all hashtag feed indices
|
||||
val hashtagIndices = db.tabsDao().getTabsChecked(user.user_id, user.instance_uri).filter {
|
||||
it.checked
|
||||
}.map {
|
||||
if (Tab.fromName(it.tab) == Tab.HASHTAG_FEED) {
|
||||
it.index
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
hashtagIndices.zip(tabs).zip(pageIds).forEach { (indexPageId, pageId) ->
|
||||
val index = indexPageId.first
|
||||
val tabId = indexPageId.second
|
||||
|
||||
with(bottomNavigationMenu?.add(R.id.tabsId, pageId, 1, tabId.toLanguageString(this@MainActivity, db, index, true))) {
|
||||
val tabIcon = tabId.getDrawable(this@MainActivity)
|
||||
if (tabIcon != null) {
|
||||
this?.icon = tabIcon
|
||||
}
|
||||
|
|
|
@ -4,11 +4,15 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.PagingDataAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.posts.StatusViewHolder
|
||||
import org.pixeldroid.app.posts.feeds.UIMODEL_STATUS_COMPARATOR
|
||||
|
@ -19,6 +23,7 @@ import org.pixeldroid.app.utils.api.objects.Status
|
|||
import org.pixeldroid.app.utils.api.objects.Tag.Companion.HASHTAG_TAG
|
||||
import org.pixeldroid.app.utils.displayDimensionsInPx
|
||||
|
||||
|
||||
/**
|
||||
* Fragment to show a list of [Status]es, as a result of a search or a hashtag.
|
||||
*/
|
||||
|
@ -33,7 +38,7 @@ class UncachedPostsFragment : UncachedFeedFragment<Status>() {
|
|||
|
||||
hashtagOrQuery = arguments?.getString(HASHTAG_TAG)
|
||||
|
||||
if(hashtagOrQuery == null){
|
||||
if (hashtagOrQuery == null) {
|
||||
search = true
|
||||
hashtagOrQuery = arguments?.getString("searchFeed")!!
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
|
@ -22,6 +23,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.utils.Tab
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.db.entities.TabsDatabaseEntity
|
||||
import javax.inject.Inject
|
||||
|
@ -39,7 +41,8 @@ class ArrangeTabsFragment: DialogFragment() {
|
|||
val inflater: LayoutInflater = requireActivity().layoutInflater
|
||||
val dialogView: View = inflater.inflate(R.layout.layout_tabs_arrange, null)
|
||||
|
||||
model.initTabsChecked()
|
||||
val itemCount = model.initTabsChecked()
|
||||
model.initTabsButtons(itemCount, requireContext())
|
||||
|
||||
val listFeed: RecyclerView = dialogView.findViewById(R.id.tabs)
|
||||
val listAdapter = ListViewAdapter(model)
|
||||
|
@ -71,7 +74,7 @@ class ArrangeTabsFragment: DialogFragment() {
|
|||
// Save values into preferences
|
||||
val tabsChecked = listAdapter.model.uiState.value.tabsChecked.toList()
|
||||
val tabsDbEntity = tabsChecked.mapIndexed { index, (tab, checked) -> with (db.userDao().getActiveUser()!!) {
|
||||
TabsDatabaseEntity(index, user_id, instance_uri, tab.name, checked)
|
||||
TabsDatabaseEntity(index, user_id, instance_uri, tab.name, checked, tab.filter)
|
||||
} }
|
||||
lifecycleScope.launch {
|
||||
db.tabsDao().clearAndRefill(tabsDbEntity, model.uiState.value.userId, model.uiState.value.instanceUri)
|
||||
|
@ -103,20 +106,59 @@ class ArrangeTabsFragment: DialogFragment() {
|
|||
val checkBox: MaterialCheckBox = holder.itemView.findViewById(R.id.checkBox)
|
||||
val dragHandle: ImageView = holder.itemView.findViewById(R.id.dragHandle)
|
||||
|
||||
val tabText = model.getTabsButtons(position)
|
||||
|
||||
// Set content of each entry
|
||||
textView.text = model.uiState.value.tabsChecked[position].first.toLanguageString(requireContext())
|
||||
if (tabText != null) {
|
||||
textView.text = tabText
|
||||
} else {
|
||||
model.updateTabsButtons(position, model.uiState.value.tabsChecked[position].first.toLanguageString(requireContext(), db, position, true))
|
||||
textView.text = model.getTabsButtons(position)
|
||||
}
|
||||
checkBox.isChecked = model.uiState.value.tabsChecked[position].second
|
||||
|
||||
// Also interact with checkbox when button is clicked
|
||||
textView.setOnClickListener {
|
||||
val isCheckedNew = !model.uiState.value.tabsChecked[position].second
|
||||
model.tabsCheckReplace(position, Pair(model.uiState.value.tabsChecked[position].first, isCheckedNew))
|
||||
fun callbackOnClickListener(tabNew: Tab, isCheckedNew: Boolean, hashtag: String? = null) {
|
||||
tabNew.filter = hashtag?.split("#")?.filter { it.isNotBlank() }?.get(0)
|
||||
model.tabsCheckReplace(position, Pair(tabNew, isCheckedNew))
|
||||
checkBox.isChecked = isCheckedNew
|
||||
|
||||
val hashtagWithHashtag = tabNew.filter?.let {
|
||||
StringBuilder("#").append(it).toString()
|
||||
}
|
||||
|
||||
// Disable OK button when no tab is selected or when strictly more than 5 tabs are selected
|
||||
val maxItemCount = BottomNavigationView(requireContext()).maxItemCount // = 5
|
||||
(requireDialog() as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)?.isEnabled =
|
||||
with (model.uiState.value.tabsChecked.count { (_, v) -> v }) { this in 1..maxItemCount}
|
||||
model.updateTabsButtons(position, hashtagWithHashtag ?: model.uiState.value.tabsChecked[position].first.toLanguageString(requireContext(), db, position, false))
|
||||
textView.text = model.getTabsButtons(position)
|
||||
}
|
||||
|
||||
// Also interact with checkbox when button is clicked
|
||||
textView.setOnClickListener {
|
||||
val isCheckedNew = !model.uiState.value.tabsChecked[position].second
|
||||
val tabNew = model.uiState.value.tabsChecked[position].first
|
||||
|
||||
if (tabNew == Tab.HASHTAG_FEED && isCheckedNew) {
|
||||
// Ask which hashtag should filter
|
||||
val textField = EditText(requireContext())
|
||||
|
||||
// Set the default text to a link of the Queen
|
||||
textField.hint = "hashtag"
|
||||
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(getString(R.string.feed_hashtag))
|
||||
.setMessage(getString(R.string.feed_hashtag_description))
|
||||
.setView(textField)
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val hashtag = textField.text.toString()
|
||||
callbackOnClickListener(tabNew, isCheckedNew, hashtag)
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
callbackOnClickListener(tabNew, isCheckedNew)
|
||||
}
|
||||
}
|
||||
|
||||
// Also highlight button when checkbox is clicked
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package org.pixeldroid.app.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.EditText
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
@ -20,6 +24,7 @@ class ArrangeTabsViewModel @Inject constructor(
|
|||
val uiState: StateFlow<ArrangeTabsUiState> = _uiState
|
||||
|
||||
private var oldTabsChecked: MutableList<Pair<Tab, Boolean>> = mutableListOf()
|
||||
private var oldTabsButtons: MutableList<String?> = mutableListOf()
|
||||
|
||||
init {
|
||||
initTabsDbEntities()
|
||||
|
@ -40,7 +45,7 @@ class ArrangeTabsViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun initTabsChecked() {
|
||||
fun initTabsChecked(): Int {
|
||||
if (oldTabsChecked.isEmpty()) {
|
||||
// Only load tabsChecked if the model has not been updated
|
||||
_uiState.update { currentUiState ->
|
||||
|
@ -55,6 +60,18 @@ class ArrangeTabsViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
return _uiState.value.tabsChecked.size
|
||||
}
|
||||
|
||||
fun initTabsButtons(itemCount: Int, ctx: Context) {
|
||||
oldTabsChecked = _uiState.value.tabsChecked.toMutableList()
|
||||
if (oldTabsButtons.isEmpty()) {
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
tabsButtons = (0 until itemCount).map { null }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tabsCheckReplace(position: Int, pair: Pair<Tab, Boolean>) {
|
||||
|
@ -87,11 +104,26 @@ class ArrangeTabsViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTabsButtons(position: Int, text: String) {
|
||||
oldTabsButtons = _uiState.value.tabsButtons.toMutableList()
|
||||
oldTabsButtons[position] = text
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
tabsButtons = oldTabsButtons.toList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getTabsButtons(position: Int): String? {
|
||||
return _uiState.value.tabsButtons[position]
|
||||
}
|
||||
}
|
||||
|
||||
data class ArrangeTabsUiState(
|
||||
val userId: String = "",
|
||||
val instanceUri: String = "",
|
||||
val tabsDbEntities: List<TabsDatabaseEntity> = listOf(),
|
||||
val tabsChecked: List<Pair<Tab, Boolean>> = listOf()
|
||||
val tabsChecked: List<Pair<Tab, Boolean>> = listOf(),
|
||||
val tabsButtons: List<String?> = listOf()
|
||||
)
|
|
@ -31,6 +31,7 @@ import com.google.gson.JsonPrimitive
|
|||
import com.google.gson.JsonSerializer
|
||||
import okhttp3.HttpUrl
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.db.entities.TabsDatabaseEntity
|
||||
import java.time.Instant
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
@ -199,24 +200,35 @@ fun <T> Fragment.bindingLifecycleAware(): ReadWriteProperty<Fragment, T> =
|
|||
|
||||
fun loadDbMenuTabs(tabsDbEntry: List<TabsDatabaseEntity>): List<Pair<Tab, Boolean>> {
|
||||
return tabsDbEntry.map {
|
||||
Pair(Tab.fromName(it.tab), it.checked)
|
||||
val tab = Tab.fromName(it.tab)
|
||||
if (tab == Tab.HASHTAG_FEED) {
|
||||
tab.filter = it.filter
|
||||
}
|
||||
Pair(tab, it.checked)
|
||||
}
|
||||
}
|
||||
|
||||
enum class Tab {
|
||||
HOME_FEED, SEARCH_DISCOVER_FEED, CREATE_FEED, NOTIFICATIONS_FEED, PUBLIC_FEED, DIRECT_MESSAGES;
|
||||
enum class Tab(var filter: String? = null) {
|
||||
HOME_FEED, SEARCH_DISCOVER_FEED, CREATE_FEED, NOTIFICATIONS_FEED, PUBLIC_FEED, DIRECT_MESSAGES, HASHTAG_FEED;
|
||||
|
||||
fun toLanguageString(ctx: Context): String {
|
||||
return ctx.getString(
|
||||
when (this) {
|
||||
HOME_FEED -> R.string.home_feed
|
||||
SEARCH_DISCOVER_FEED -> R.string.search_discover_feed
|
||||
CREATE_FEED -> R.string.create_feed
|
||||
NOTIFICATIONS_FEED -> R.string.notifications_feed
|
||||
PUBLIC_FEED -> R.string.public_feed
|
||||
DIRECT_MESSAGES -> R.string.direct_messages
|
||||
fun toLanguageString(ctx: Context, db: AppDatabase, index: Int, lookForFilter: Boolean = false): String {
|
||||
return when (this) {
|
||||
HOME_FEED -> ctx.getString(R.string.home_feed)
|
||||
SEARCH_DISCOVER_FEED -> ctx.getString(R.string.search_discover_feed)
|
||||
CREATE_FEED -> ctx.getString(R.string.create_feed)
|
||||
NOTIFICATIONS_FEED -> ctx.getString(R.string.notifications_feed)
|
||||
PUBLIC_FEED -> ctx.getString(R.string.public_feed)
|
||||
DIRECT_MESSAGES -> ctx.getString(R.string.direct_messages)
|
||||
HASHTAG_FEED -> {
|
||||
val user = db.userDao().getActiveUser()!!
|
||||
val hashtag = db.tabsDao().getTabChecked(index, user.user_id, user.instance_uri)?.filter
|
||||
if (lookForFilter && hashtag != null) {
|
||||
StringBuilder("#").append(hashtag).toString()
|
||||
} else {
|
||||
ctx.getString(R.string.feed_hashtag)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toName(): String {
|
||||
|
@ -231,6 +243,7 @@ enum class Tab {
|
|||
NOTIFICATIONS_FEED -> R.drawable.selector_notifications
|
||||
PUBLIC_FEED -> R.drawable.ic_filter_black_24dp
|
||||
DIRECT_MESSAGES -> R.drawable.selector_dm
|
||||
HASHTAG_FEED -> R.drawable.feed_hashtag
|
||||
}
|
||||
return AppCompatResources.getDrawable(ctx, resId)
|
||||
}
|
||||
|
@ -244,6 +257,7 @@ enum class Tab {
|
|||
ctx.getString(R.string.notifications_feed) -> NOTIFICATIONS_FEED
|
||||
ctx.getString(R.string.public_feed) -> PUBLIC_FEED
|
||||
ctx.getString(R.string.direct_messages) -> DIRECT_MESSAGES
|
||||
ctx.getString(R.string.feed_hashtag) -> HASHTAG_FEED
|
||||
else -> HOME_FEED
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +276,8 @@ enum class Tab {
|
|||
)
|
||||
val otherTabs: List<Tab>
|
||||
get() = listOf(
|
||||
DIRECT_MESSAGES
|
||||
DIRECT_MESSAGES,
|
||||
HASHTAG_FEED
|
||||
)
|
||||
}
|
||||
}
|
|
@ -35,9 +35,10 @@ import org.pixeldroid.app.utils.db.entities.TabsDatabaseEntity
|
|||
],
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 6, to = 7),
|
||||
AutoMigration(from = 7, to = 8)
|
||||
AutoMigration(from = 7, to = 8),
|
||||
AutoMigration(from = 8, to = 9)
|
||||
],
|
||||
version = 8
|
||||
version = 9
|
||||
)
|
||||
|
||||
@TypeConverters(Converters::class)
|
||||
|
@ -68,4 +69,6 @@ val MIGRATION_5_6 = object : Migration(5, 6) {
|
|||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE instances ADD COLUMN pixelfed INTEGER NOT NULL DEFAULT 1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Manually add missing HASHTAG_FEED entry
|
|
@ -11,7 +11,7 @@ import org.pixeldroid.app.utils.db.entities.TabsDatabaseEntity
|
|||
@Dao
|
||||
interface TabsDao {
|
||||
@Query("SELECT * FROM tabsChecked WHERE `index`=:index AND `user_id`=:userId AND `instance_uri`=:instanceUri")
|
||||
fun getTabChecked(index: Int, userId: String, instanceUri: String): TabsDatabaseEntity
|
||||
fun getTabChecked(index: Int, userId: String, instanceUri: String): TabsDatabaseEntity?
|
||||
|
||||
@Query("SELECT * FROM tabsChecked WHERE `user_id`=:userId AND `instance_uri`=:instanceUri")
|
||||
fun getTabsChecked(userId: String, instanceUri: String): List<TabsDatabaseEntity>
|
||||
|
@ -28,16 +28,6 @@ interface TabsDao {
|
|||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insertTabChecked(tabChecked: TabsDatabaseEntity): Long
|
||||
|
||||
@Update
|
||||
suspend fun updateTabChecked(tabChecked: TabsDatabaseEntity)
|
||||
|
||||
@Transaction
|
||||
suspend fun insertOrUpdate(tabChecked: TabsDatabaseEntity) {
|
||||
if (insertTabChecked(tabChecked) == -1L) {
|
||||
updateTabChecked(tabChecked)
|
||||
}
|
||||
}
|
||||
|
||||
@Transaction
|
||||
suspend fun clearAndRefill(tabsChecked: List<TabsDatabaseEntity>, userId: String, instanceUri: String) {
|
||||
deleteTabsChecked(userId, instanceUri)
|
||||
|
|
|
@ -22,4 +22,5 @@ data class TabsDatabaseEntity(
|
|||
var instance_uri: String,
|
||||
var tab: String,
|
||||
var checked: Boolean = true,
|
||||
var filter: String? = null
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M20,10L20,8h-4L16,4h-2v4h-4L10,4L8,4v4L4,8v2h4v4L4,14v2h4v4h2v-4h4v4h2v-4h4v-2h-4v-4h4zM14,14h-4v-4h4v4z"/>
|
||||
</vector>
|
|
@ -354,4 +354,6 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
|
|||
|
||||
<string name="dm_title">DM to %1$s</string>
|
||||
<string name="direct_messages">Direct Messages</string>
|
||||
<string name="feed_hashtag">Hashtag Feed</string>
|
||||
<string name="feed_hashtag_description">Write a single hashtag below</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue