diff --git a/app/schemas/it.niedermann.owncloud.notes.persistence.NotesDatabase/27.json b/app/schemas/it.niedermann.owncloud.notes.persistence.NotesDatabase/27.json new file mode 100644 index 000000000..c15ecf633 --- /dev/null +++ b/app/schemas/it.niedermann.owncloud.notes.persistence.NotesDatabase/27.json @@ -0,0 +1,741 @@ +{ + "formatVersion": 1, + "database": { + "version": 27, + "identityHash": "9bb1af64fb5d0c3bbf0520e757004e1f", + "entities": [ + { + "tableName": "Account", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL DEFAULT '', `userName` TEXT NOT NULL DEFAULT '', `accountName` TEXT NOT NULL DEFAULT '', `eTag` TEXT, `modified` INTEGER, `apiVersion` TEXT, `color` INTEGER NOT NULL DEFAULT -16743735, `textColor` INTEGER NOT NULL DEFAULT -16777216, `capabilitiesETag` TEXT, `displayName` TEXT, `directEditingAvailable` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "userName", + "columnName": "userName", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "accountName", + "columnName": "accountName", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "eTag", + "columnName": "eTag", + "affinity": "TEXT" + }, + { + "fieldPath": "modified", + "columnName": "modified", + "affinity": "INTEGER" + }, + { + "fieldPath": "apiVersion", + "columnName": "apiVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-16743735" + }, + { + "fieldPath": "textColor", + "columnName": "textColor", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-16777216" + }, + { + "fieldPath": "capabilitiesETag", + "columnName": "capabilitiesETag", + "affinity": "TEXT" + }, + { + "fieldPath": "displayName", + "columnName": "displayName", + "affinity": "TEXT" + }, + { + "fieldPath": "directEditingAvailable", + "columnName": "directEditingAvailable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_ACCOUNT_MODIFIED", + "unique": false, + "columnNames": [ + "modified" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_MODIFIED` ON `${TABLE_NAME}` (`modified`)" + }, + { + "name": "IDX_ACCOUNT_URL", + "unique": false, + "columnNames": [ + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_URL` ON `${TABLE_NAME}` (`url`)" + }, + { + "name": "IDX_ACCOUNT_USERNAME", + "unique": false, + "columnNames": [ + "userName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_USERNAME` ON `${TABLE_NAME}` (`userName`)" + }, + { + "name": "IDX_ACCOUNT_ACCOUNTNAME", + "unique": false, + "columnNames": [ + "accountName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_ACCOUNTNAME` ON `${TABLE_NAME}` (`accountName`)" + }, + { + "name": "IDX_ACCOUNT_ETAG", + "unique": false, + "columnNames": [ + "eTag" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_ETAG` ON `${TABLE_NAME}` (`eTag`)" + } + ] + }, + { + "tableName": "Note", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remoteId` INTEGER, `accountId` INTEGER NOT NULL, `status` TEXT NOT NULL, `title` TEXT NOT NULL DEFAULT '', `category` TEXT NOT NULL DEFAULT '', `modified` INTEGER, `content` TEXT NOT NULL DEFAULT '', `favorite` INTEGER NOT NULL DEFAULT 0, `isShared` INTEGER NOT NULL DEFAULT 0, `readonly` INTEGER NOT NULL DEFAULT 0, `eTag` TEXT, `excerpt` TEXT NOT NULL DEFAULT '', `scrollY` INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER" + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "modified", + "columnName": "modified", + "affinity": "INTEGER" + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "favorite", + "columnName": "favorite", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "isShared", + "columnName": "isShared", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "readonly", + "columnName": "readonly", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "eTag", + "columnName": "eTag", + "affinity": "TEXT" + }, + { + "fieldPath": "excerpt", + "columnName": "excerpt", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "scrollY", + "columnName": "scrollY", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_NOTE_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_NOTE_CATEGORY", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_CATEGORY` ON `${TABLE_NAME}` (`category`)" + }, + { + "name": "IDX_NOTE_FAVORITE", + "unique": false, + "columnNames": [ + "favorite" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_FAVORITE` ON `${TABLE_NAME}` (`favorite`)" + }, + { + "name": "IDX_NOTE_IS_SHARED", + "unique": false, + "columnNames": [ + "isShared" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_IS_SHARED` ON `${TABLE_NAME}` (`isShared`)" + }, + { + "name": "IDX_READONLY", + "unique": false, + "columnNames": [ + "readonly" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_READONLY` ON `${TABLE_NAME}` (`readonly`)" + }, + { + "name": "IDX_NOTE_MODIFIED", + "unique": false, + "columnNames": [ + "modified" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_MODIFIED` ON `${TABLE_NAME}` (`modified`)" + }, + { + "name": "IDX_NOTE_REMOTEID", + "unique": false, + "columnNames": [ + "remoteId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_REMOTEID` ON `${TABLE_NAME}` (`remoteId`)" + }, + { + "name": "IDX_NOTE_STATUS", + "unique": false, + "columnNames": [ + "status" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_STATUS` ON `${TABLE_NAME}` (`status`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "CategoryOptions", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `category` TEXT NOT NULL, `sortingMethod` INTEGER, PRIMARY KEY(`accountId`, `category`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortingMethod", + "columnName": "sortingMethod", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId", + "category" + ] + }, + "indices": [ + { + "name": "IDX_CATEGORIYOPTIONS_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_CATEGORIYOPTIONS_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_CATEGORIYOPTIONS_CATEGORY", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_CATEGORIYOPTIONS_CATEGORY` ON `${TABLE_NAME}` (`category`)" + }, + { + "name": "IDX_CATEGORIYOPTIONS_SORTING_METHOD", + "unique": false, + "columnNames": [ + "sortingMethod" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_CATEGORIYOPTIONS_SORTING_METHOD` ON `${TABLE_NAME}` (`sortingMethod`)" + }, + { + "name": "IDX_UNIQUE_CATEGORYOPTIONS_ACCOUNT_CATEGORY", + "unique": true, + "columnNames": [ + "accountId", + "category" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `IDX_UNIQUE_CATEGORYOPTIONS_ACCOUNT_CATEGORY` ON `${TABLE_NAME}` (`accountId`, `category`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "SingleNoteWidgetData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`noteId` INTEGER NOT NULL, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`noteId`) REFERENCES `Note`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "noteId", + "columnName": "noteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "themeMode", + "columnName": "themeMode", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_SINGLENOTEWIDGETDATA_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_SINGLENOTEWIDGETDATA_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_SINGLENOTEWIDGETDATA_NOTEID", + "unique": false, + "columnNames": [ + "noteId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_SINGLENOTEWIDGETDATA_NOTEID` ON `${TABLE_NAME}` (`noteId`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "Note", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "noteId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "NotesListWidgetData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mode` INTEGER NOT NULL, `category` TEXT, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "mode", + "columnName": "mode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT" + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "themeMode", + "columnName": "themeMode", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_NOTESLISTWIDGETDATA_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTESLISTWIDGETDATA_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_NOTESLISTWIDGETDATA_CATEGORY", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTESLISTWIDGETDATA_CATEGORY` ON `${TABLE_NAME}` (`category`)" + }, + { + "name": "IDX_NOTESLISTWIDGETDATA_ACCOUNT_CATEGORY", + "unique": false, + "columnNames": [ + "accountId", + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTESLISTWIDGETDATA_ACCOUNT_CATEGORY` ON `${TABLE_NAME}` (`accountId`, `category`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "share_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `note` TEXT, `path` TEXT, `file_target` TEXT, `share_with` TEXT, `share_with_displayname` TEXT, `uid_file_owner` TEXT, `displayname_file_owner` TEXT, `uid_owner` TEXT, `displayname_owner` TEXT, `url` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT" + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT" + }, + { + "fieldPath": "file_target", + "columnName": "file_target", + "affinity": "TEXT" + }, + { + "fieldPath": "share_with", + "columnName": "share_with", + "affinity": "TEXT" + }, + { + "fieldPath": "share_with_displayname", + "columnName": "share_with_displayname", + "affinity": "TEXT" + }, + { + "fieldPath": "uid_file_owner", + "columnName": "uid_file_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "displayname_file_owner", + "columnName": "displayname_file_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "uid_owner", + "columnName": "uid_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "displayname_owner", + "columnName": "displayname_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "capabilities", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `nextcloudMajorVersion` TEXT, `nextcloudMinorVersion` TEXT, `nextcloudMicroVersion` TEXT, `federationShare` INTEGER NOT NULL, `apiVersion` TEXT, `color` INTEGER NOT NULL, `textColor` INTEGER NOT NULL, `eTag` TEXT, `directEditingAvailable` INTEGER NOT NULL, `publicPasswordEnforced` INTEGER NOT NULL, `askForOptionalPassword` INTEGER NOT NULL, `isReSharingAllowed` INTEGER NOT NULL, `defaultPermission` INTEGER NOT NULL, `userStatusSupportsBusy` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "nextcloudMajorVersion", + "columnName": "nextcloudMajorVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "nextcloudMinorVersion", + "columnName": "nextcloudMinorVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "nextcloudMicroVersion", + "columnName": "nextcloudMicroVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "federationShare", + "columnName": "federationShare", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "apiVersion", + "columnName": "apiVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "textColor", + "columnName": "textColor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "eTag", + "columnName": "eTag", + "affinity": "TEXT" + }, + { + "fieldPath": "directEditingAvailable", + "columnName": "directEditingAvailable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "publicPasswordEnforced", + "columnName": "publicPasswordEnforced", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "askForOptionalPassword", + "columnName": "askForOptionalPassword", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isReSharingAllowed", + "columnName": "isReSharingAllowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "defaultPermission", + "columnName": "defaultPermission", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userStatusSupportsBusy", + "columnName": "userStatusSupportsBusy", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + } + ], + "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, '9bb1af64fb5d0c3bbf0520e757004e1f')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/it.niedermann.owncloud.notes.persistence.NotesDatabase/28.json b/app/schemas/it.niedermann.owncloud.notes.persistence.NotesDatabase/28.json new file mode 100644 index 000000000..2b29bad82 --- /dev/null +++ b/app/schemas/it.niedermann.owncloud.notes.persistence.NotesDatabase/28.json @@ -0,0 +1,746 @@ +{ + "formatVersion": 1, + "database": { + "version": 28, + "identityHash": "dbd2dac6b2b2c1e6626351a82ab7d88d", + "entities": [ + { + "tableName": "Account", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL DEFAULT '', `userName` TEXT NOT NULL DEFAULT '', `accountName` TEXT NOT NULL DEFAULT '', `eTag` TEXT, `modified` INTEGER, `apiVersion` TEXT, `color` INTEGER NOT NULL DEFAULT -16743735, `textColor` INTEGER NOT NULL DEFAULT -16777216, `capabilitiesETag` TEXT, `displayName` TEXT, `directEditingAvailable` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "userName", + "columnName": "userName", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "accountName", + "columnName": "accountName", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "eTag", + "columnName": "eTag", + "affinity": "TEXT" + }, + { + "fieldPath": "modified", + "columnName": "modified", + "affinity": "INTEGER" + }, + { + "fieldPath": "apiVersion", + "columnName": "apiVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-16743735" + }, + { + "fieldPath": "textColor", + "columnName": "textColor", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-16777216" + }, + { + "fieldPath": "capabilitiesETag", + "columnName": "capabilitiesETag", + "affinity": "TEXT" + }, + { + "fieldPath": "displayName", + "columnName": "displayName", + "affinity": "TEXT" + }, + { + "fieldPath": "directEditingAvailable", + "columnName": "directEditingAvailable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_ACCOUNT_MODIFIED", + "unique": false, + "columnNames": [ + "modified" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_MODIFIED` ON `${TABLE_NAME}` (`modified`)" + }, + { + "name": "IDX_ACCOUNT_URL", + "unique": false, + "columnNames": [ + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_URL` ON `${TABLE_NAME}` (`url`)" + }, + { + "name": "IDX_ACCOUNT_USERNAME", + "unique": false, + "columnNames": [ + "userName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_USERNAME` ON `${TABLE_NAME}` (`userName`)" + }, + { + "name": "IDX_ACCOUNT_ACCOUNTNAME", + "unique": false, + "columnNames": [ + "accountName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_ACCOUNTNAME` ON `${TABLE_NAME}` (`accountName`)" + }, + { + "name": "IDX_ACCOUNT_ETAG", + "unique": false, + "columnNames": [ + "eTag" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_ACCOUNT_ETAG` ON `${TABLE_NAME}` (`eTag`)" + } + ] + }, + { + "tableName": "Note", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remoteId` INTEGER, `accountId` INTEGER NOT NULL, `status` TEXT NOT NULL, `title` TEXT NOT NULL DEFAULT '', `category` TEXT NOT NULL DEFAULT '', `modified` INTEGER, `content` TEXT NOT NULL DEFAULT '', `favorite` INTEGER NOT NULL DEFAULT 0, `isShared` INTEGER NOT NULL DEFAULT 0, `readonly` INTEGER NOT NULL DEFAULT 0, `eTag` TEXT, `excerpt` TEXT NOT NULL DEFAULT '', `scrollY` INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER" + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "modified", + "columnName": "modified", + "affinity": "INTEGER" + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "favorite", + "columnName": "favorite", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "isShared", + "columnName": "isShared", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "readonly", + "columnName": "readonly", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "eTag", + "columnName": "eTag", + "affinity": "TEXT" + }, + { + "fieldPath": "excerpt", + "columnName": "excerpt", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "scrollY", + "columnName": "scrollY", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_NOTE_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_NOTE_CATEGORY", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_CATEGORY` ON `${TABLE_NAME}` (`category`)" + }, + { + "name": "IDX_NOTE_FAVORITE", + "unique": false, + "columnNames": [ + "favorite" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_FAVORITE` ON `${TABLE_NAME}` (`favorite`)" + }, + { + "name": "IDX_NOTE_IS_SHARED", + "unique": false, + "columnNames": [ + "isShared" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_IS_SHARED` ON `${TABLE_NAME}` (`isShared`)" + }, + { + "name": "IDX_READONLY", + "unique": false, + "columnNames": [ + "readonly" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_READONLY` ON `${TABLE_NAME}` (`readonly`)" + }, + { + "name": "IDX_NOTE_MODIFIED", + "unique": false, + "columnNames": [ + "modified" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_MODIFIED` ON `${TABLE_NAME}` (`modified`)" + }, + { + "name": "IDX_NOTE_REMOTEID", + "unique": false, + "columnNames": [ + "remoteId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_REMOTEID` ON `${TABLE_NAME}` (`remoteId`)" + }, + { + "name": "IDX_NOTE_STATUS", + "unique": false, + "columnNames": [ + "status" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTE_STATUS` ON `${TABLE_NAME}` (`status`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "CategoryOptions", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `category` TEXT NOT NULL, `sortingMethod` INTEGER, PRIMARY KEY(`accountId`, `category`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortingMethod", + "columnName": "sortingMethod", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId", + "category" + ] + }, + "indices": [ + { + "name": "IDX_CATEGORIYOPTIONS_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_CATEGORIYOPTIONS_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_CATEGORIYOPTIONS_CATEGORY", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_CATEGORIYOPTIONS_CATEGORY` ON `${TABLE_NAME}` (`category`)" + }, + { + "name": "IDX_CATEGORIYOPTIONS_SORTING_METHOD", + "unique": false, + "columnNames": [ + "sortingMethod" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_CATEGORIYOPTIONS_SORTING_METHOD` ON `${TABLE_NAME}` (`sortingMethod`)" + }, + { + "name": "IDX_UNIQUE_CATEGORYOPTIONS_ACCOUNT_CATEGORY", + "unique": true, + "columnNames": [ + "accountId", + "category" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `IDX_UNIQUE_CATEGORYOPTIONS_ACCOUNT_CATEGORY` ON `${TABLE_NAME}` (`accountId`, `category`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "SingleNoteWidgetData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`noteId` INTEGER NOT NULL, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`noteId`) REFERENCES `Note`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "noteId", + "columnName": "noteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "themeMode", + "columnName": "themeMode", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_SINGLENOTEWIDGETDATA_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_SINGLENOTEWIDGETDATA_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_SINGLENOTEWIDGETDATA_NOTEID", + "unique": false, + "columnNames": [ + "noteId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_SINGLENOTEWIDGETDATA_NOTEID` ON `${TABLE_NAME}` (`noteId`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "Note", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "noteId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "NotesListWidgetData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`mode` INTEGER NOT NULL, `category` TEXT, `id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `themeMode` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "mode", + "columnName": "mode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT" + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "themeMode", + "columnName": "themeMode", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "IDX_NOTESLISTWIDGETDATA_ACCOUNTID", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTESLISTWIDGETDATA_ACCOUNTID` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "IDX_NOTESLISTWIDGETDATA_CATEGORY", + "unique": false, + "columnNames": [ + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTESLISTWIDGETDATA_CATEGORY` ON `${TABLE_NAME}` (`category`)" + }, + { + "name": "IDX_NOTESLISTWIDGETDATA_ACCOUNT_CATEGORY", + "unique": false, + "columnNames": [ + "accountId", + "category" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `IDX_NOTESLISTWIDGETDATA_ACCOUNT_CATEGORY` ON `${TABLE_NAME}` (`accountId`, `category`)" + } + ], + "foreignKeys": [ + { + "table": "Account", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "share_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `note` TEXT, `path` TEXT, `file_target` TEXT, `share_with` TEXT, `share_with_displayname` TEXT, `uid_file_owner` TEXT, `displayname_file_owner` TEXT, `uid_owner` TEXT, `displayname_owner` TEXT, `url` TEXT, `expiration_date` INTEGER)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT" + }, + { + "fieldPath": "path", + "columnName": "path", + "affinity": "TEXT" + }, + { + "fieldPath": "file_target", + "columnName": "file_target", + "affinity": "TEXT" + }, + { + "fieldPath": "share_with", + "columnName": "share_with", + "affinity": "TEXT" + }, + { + "fieldPath": "share_with_displayname", + "columnName": "share_with_displayname", + "affinity": "TEXT" + }, + { + "fieldPath": "uid_file_owner", + "columnName": "uid_file_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "displayname_file_owner", + "columnName": "displayname_file_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "uid_owner", + "columnName": "uid_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "displayname_owner", + "columnName": "displayname_owner", + "affinity": "TEXT" + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT" + }, + { + "fieldPath": "expiration_date", + "columnName": "expiration_date", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "capabilities", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `nextcloudMajorVersion` TEXT, `nextcloudMinorVersion` TEXT, `nextcloudMicroVersion` TEXT, `federationShare` INTEGER NOT NULL, `apiVersion` TEXT, `color` INTEGER NOT NULL, `textColor` INTEGER NOT NULL, `eTag` TEXT, `directEditingAvailable` INTEGER NOT NULL, `publicPasswordEnforced` INTEGER NOT NULL, `askForOptionalPassword` INTEGER NOT NULL, `isReSharingAllowed` INTEGER NOT NULL, `defaultPermission` INTEGER NOT NULL, `userStatusSupportsBusy` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "nextcloudMajorVersion", + "columnName": "nextcloudMajorVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "nextcloudMinorVersion", + "columnName": "nextcloudMinorVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "nextcloudMicroVersion", + "columnName": "nextcloudMicroVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "federationShare", + "columnName": "federationShare", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "apiVersion", + "columnName": "apiVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "textColor", + "columnName": "textColor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "eTag", + "columnName": "eTag", + "affinity": "TEXT" + }, + { + "fieldPath": "directEditingAvailable", + "columnName": "directEditingAvailable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "publicPasswordEnforced", + "columnName": "publicPasswordEnforced", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "askForOptionalPassword", + "columnName": "askForOptionalPassword", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isReSharingAllowed", + "columnName": "isReSharingAllowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "defaultPermission", + "columnName": "defaultPermission", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userStatusSupportsBusy", + "columnName": "userStatusSupportsBusy", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + } + ], + "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, 'dbd2dac6b2b2c1e6626351a82ab7d88d')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/NotesViewThemeUtils.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/NotesViewThemeUtils.java index 59f9d4251..1af73126d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/NotesViewThemeUtils.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/NotesViewThemeUtils.java @@ -19,6 +19,7 @@ import android.util.Log; import android.view.View; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.ColorInt; @@ -28,7 +29,6 @@ import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; -import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.drawable.DrawableCompat; import com.google.android.material.appbar.AppBarLayout; @@ -220,6 +220,28 @@ public void themeToolbarSearchView(@NonNull SearchView searchView) { }); } + /** + * @deprecated Should be replaced with {@link com.google.android.material.search.SearchView} + */ + @Deprecated + public void themeContentSearchView(@NonNull SearchView searchView) { + withScheme(searchView, scheme -> { + // hacky as no default way is provided + final var editText = (AppCompatAutoCompleteTextView) searchView + .findViewById(androidx.appcompat.R.id.search_src_text); + final var searchPlate = (LinearLayout) searchView.findViewById(androidx.appcompat.R.id.search_plate); + final var closeButton = (ImageView) searchView.findViewById(androidx.appcompat.R.id.search_close_btn); + final var searchButton = (ImageView) searchView.findViewById(androidx.appcompat.R.id.search_button); + editText.setHintTextColor(dynamicColor.onSurfaceVariant().getArgb(scheme)); + editText.setHighlightColor(dynamicColor.inverseOnSurface().getArgb(scheme)); + editText.setTextColor(dynamicColor.onSurface().getArgb(scheme)); + closeButton.setColorFilter(dynamicColor.onSurface().getArgb(scheme)); + searchButton.setColorFilter(dynamicColor.onSurface().getArgb(scheme)); + searchPlate.setBackgroundColor(dynamicColor.surfaceContainerHigh().getArgb(scheme)); + return searchView; + }); + } + public void themeInternalLinkIcon(ImageView view) { withScheme(view, scheme -> { view diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java index 6fd0b6cb4..f711af4ca 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java @@ -58,10 +58,11 @@ NotesListWidgetData.class, ShareEntity.class, Capabilities.class - }, version = 27, + }, version = 28, autoMigrations = { @AutoMigration(from = 25, to = 26), @AutoMigration(from = 26, to = 27), + @AutoMigration(from = 27, to = 28), } ) @TypeConverters({Converters.class}) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/ShareEntity.kt b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/ShareEntity.kt index 7a4ea8208..c8bfd4fcf 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/ShareEntity.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/entity/ShareEntity.kt @@ -24,5 +24,6 @@ data class ShareEntity( val displayname_file_owner: String? = null, val uid_owner: String? = null, val displayname_owner: String? = null, - val url: String? = null + val url: String? = null, + val expiration_date: Long? = null ) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java index 761280000..153d92e2e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/NoteShareActivity.java @@ -44,8 +44,10 @@ import org.jetbrains.annotations.NotNull; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -466,6 +468,22 @@ public void showSharingMenuActionSheet(OCShare share) { } } + @Override + public void showShareExpirationSnackbar(OCShare share) { + String expirationDescription = getString( + R.string.share_expires, + SimpleDateFormat.getDateInstance().format(new Date(share.getExpirationDate())) + ); + Snackbar snackbar = Snackbar + .make(binding.getRoot(), expirationDescription, Snackbar.LENGTH_LONG) + .setAction(R.string.dismiss, view -> { + // Clicking on empty action will dismiss snackbar + }); + final var util = BrandingUtil.of(BrandingUtil.readBrandMainColor(this), this); + util.material.themeSnackbar(snackbar); + snackbar.show(); + } + @Override public void showPermissionsDialog(OCShare share) { new QuickSharingPermissionsBottomSheetDialog(this, this, share).show(); @@ -807,12 +825,17 @@ public void applyBrand(int color) { final var util = BrandingUtil.of(color, this); util.platform.themeStatusBar(this); util.material.themeToolbar(binding.toolbar); - util.androidx.themeToolbarSearchView(binding.searchView); + util.notes.themeContentSearchView(binding.searchView); + util.platform.colorImageView(binding.searchViewIcon, ColorRole.ON_SURFACE_VARIANT); + util.platform.colorImageView(binding.pickContactEmailBtn, ColorRole.ON_SURFACE_VARIANT); util.platform.colorCircularProgressBar(binding.loadingLayoutIndicator, ColorRole.PRIMARY); util.platform.themeHorizontalProgressBar(binding.progressBar); util.platform.colorViewBackground(getWindow().getDecorView()); util.platform.colorViewBackground(binding.getRoot()); util.material.colorMaterialButtonPrimaryOutlined(binding.btnShareButton); + util.platform.colorTextView(binding.title, ColorRole.ON_SURFACE); + util.platform.colorTextView(binding.fileName, ColorRole.ON_SURFACE_VARIANT); + util.notes.themeSearchCardView(binding.searchCardWrapper); } @Override diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/SuggestionAdapter.kt b/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/SuggestionAdapter.kt index fd1b36f85..6348ae489 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/SuggestionAdapter.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/SuggestionAdapter.kt @@ -19,13 +19,28 @@ import androidx.core.database.getIntOrNull import androidx.core.database.getStringOrNull import androidx.cursoradapter.widget.CursorAdapter import it.niedermann.owncloud.notes.R +import it.niedermann.owncloud.notes.branding.BrandingUtil +import it.niedermann.owncloud.notes.databinding.ItemSuggestionAdapterBinding import it.niedermann.owncloud.notes.persistence.entity.Account import it.niedermann.owncloud.notes.share.helper.AvatarLoader -class SuggestionAdapter(context: Context, cursor: Cursor?, private val account: Account) : CursorAdapter(context, cursor, false) { +/** + * [CursorAdapter] used to display search suggestions for sharees for sharing notes. + * + * This adapter handles the layout and binding of suggestion data, including the + * display of user avatars or system icons based on the provided search cursor. + * + * @param context The [Context] in which the adapter is running. + * @param cursor The [Cursor] from which to get the data. + * @param account The [Account] used for loading authenticated avatars. + */ +class SuggestionAdapter(context: Context, cursor: Cursor?, private val account: Account) : + CursorAdapter(context, cursor, false) { override fun newView(context: Context, cursor: Cursor, parent: ViewGroup): View { - val inflater = LayoutInflater.from(context) - return inflater.inflate(R.layout.item_suggestion_adapter, parent, false) + val binding = ItemSuggestionAdapterBinding.inflate(LayoutInflater.from(context), parent, false) + val brandingUtil = BrandingUtil.of(BrandingUtil.readBrandMainColor(parent.context), parent.context) + binding.root.setBackgroundColor(brandingUtil.getScheme(parent.context).surfaceContainerHigh) + return binding.root } override fun bindView(view: View, context: Context, cursor: Cursor) { @@ -33,7 +48,6 @@ class SuggestionAdapter(context: Context, cursor: Cursor?, private val account: cursor.getString(cursor.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1)) view.findViewById(R.id.suggestion_text).text = suggestion - val icon = view.findViewById(R.id.suggestion_icon) val iconColumn = cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/holder/LinkShareViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/holder/LinkShareViewHolder.java index 3960649b9..58ed535f2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/holder/LinkShareViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/adapter/holder/LinkShareViewHolder.java @@ -7,11 +7,9 @@ package it.niedermann.owncloud.notes.share.adapter.holder; import android.content.Context; -import android.graphics.PorterDuff; import android.text.TextUtils; import android.view.View; -import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.core.content.res.ResourcesCompat; @@ -19,6 +17,9 @@ import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.ShareType; +import java.text.SimpleDateFormat; +import java.util.Date; + import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.BrandedViewHolder; import it.niedermann.owncloud.notes.branding.BrandingUtil; @@ -83,6 +84,21 @@ public void bind(OCShare publicShare, ShareeListAdapterListener listener) { binding.shareByLinkContainer.setOnClickListener(v -> listener.showPermissionsDialog(publicShare)); } + if (publicShare.getExpirationDate() > 0) { + String expirationDescription = context.getString( + R.string.share_expires, + SimpleDateFormat.getDateInstance().format(new Date(publicShare.getExpirationDate())) + ); + binding.expirationStatus.setContentDescription(expirationDescription); + binding.expirationStatus.setVisibility(View.VISIBLE); + binding.shareIconContainer.setOnClickListener( + v -> listener.showShareExpirationSnackbar(publicShare) + ); + } else { + binding.expirationStatus.setContentDescription(null); + binding.expirationStatus.setVisibility(View.GONE); + } + binding.copyLink.setOnClickListener(v -> listener.copyLink(publicShare)); } @@ -102,6 +118,7 @@ public void applyBrand(int color) { brandingUtil.androidx.colorPrimaryTextViewElement(binding.permissionName); brandingUtil.platform.colorTextView(binding.label, ColorRole.ON_SURFACE); brandingUtil.platform.colorImageViewBackgroundAndIcon(binding.icon); + brandingUtil.platform.colorImageView(binding.expirationStatus, ColorRole.ON_PRIMARY_CONTAINER); } } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/listener/ShareeListAdapterListener.java b/app/src/main/java/it/niedermann/owncloud/notes/share/listener/ShareeListAdapterListener.java index d87322569..3dec8f1eb 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/listener/ShareeListAdapterListener.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/listener/ShareeListAdapterListener.java @@ -15,6 +15,8 @@ public interface ShareeListAdapterListener { void showSharingMenuActionSheet(OCShare share); + void showShareExpirationSnackbar(OCShare share); + void copyInternalLink(); void createPublicShareLink(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponse.kt b/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponse.kt index eeb09c171..ec633cc38 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponse.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponse.kt @@ -139,5 +139,9 @@ data class CreateShareResponse( @Expose @SerializedName("password") - val password: String? + val password: String?, + + @Expose + @SerializedName("expiration") + val expirationDate: String? ) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponseExtensions.kt b/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponseExtensions.kt index 1d9721fc8..57cb7415e 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponseExtensions.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/model/CreateShareResponseExtensions.kt @@ -8,12 +8,18 @@ package it.niedermann.owncloud.notes.share.model import com.owncloud.android.lib.resources.shares.OCShare import com.owncloud.android.lib.resources.shares.ShareType +import it.niedermann.owncloud.notes.shared.util.extensions.toExpirationDateLong -fun List.toOCShareList(): List { - return map { response -> - response.toOCShare() - }.filter { it.id != -1L } -} +/** + * Maps a list of [CreateShareResponse] to a list of [OCShare] objects. + * + * Filters out any responses that could not be parsed correctly (where the ID is -1). + * + * @return A list of valid [OCShare] instances. + */ +fun List.toOCShareList(): List = map { response -> + response.toOCShare() +}.filter { it.id != -1L } fun CreateShareResponse.toOCShare(): OCShare { val response = this @@ -31,7 +37,7 @@ fun CreateShareResponse.toOCShare(): OCShare { sharedWithDisplayName = response.shareWithDisplayname isFolder = response.itemType == "folder" userId = response.uidOwner - shareLink = response.url + shareLink = response.url isPasswordProtected = !response.password.isNullOrEmpty() note = response.note isHideFileDownload = (response.hideDownload == 1L) @@ -39,5 +45,6 @@ fun CreateShareResponse.toOCShare(): OCShare { isHasPreview = response.hasPreview mimetype = response.mimetype ownerDisplayName = response.displaynameOwner + expirationDate = response.expirationDate?.toExpirationDateLong() ?: 0L } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/share/repository/ShareRepository.kt b/app/src/main/java/it/niedermann/owncloud/notes/share/repository/ShareRepository.kt index f9be06f2e..8b7c7e478 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/share/repository/ShareRepository.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/share/repository/ShareRepository.kt @@ -33,6 +33,7 @@ import it.niedermann.owncloud.notes.shared.model.NotesSettings import it.niedermann.owncloud.notes.shared.model.OcsResponse import it.niedermann.owncloud.notes.shared.util.StringConstants import it.niedermann.owncloud.notes.shared.util.extensions.getErrorMessage +import it.niedermann.owncloud.notes.shared.util.extensions.toExpirationDateLong import it.niedermann.owncloud.notes.shared.util.extensions.toExpirationDateString import org.json.JSONObject import java.util.Date @@ -109,6 +110,7 @@ class ShareRepository(private val applicationContext: Context, private val accou val uidOwner = map?.get("uid_owner") as? String val displayNameOwner = map?.get("displayname_owner") as? String val url = map?.get("url") as? String + val expirationDateString = map?.get("expiration") as? String id?.toInt()?.let { val entity = ShareEntity( @@ -122,7 +124,8 @@ class ShareRepository(private val applicationContext: Context, private val accou displayname_file_owner = displayNameFileOwner, uid_owner = uidOwner, displayname_owner = displayNameOwner, - url = url + url = url, + expiration_date = expirationDateString?.toExpirationDateLong() ) entities.add(entity) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/extensions/DateExtensions.kt b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/extensions/DateExtensions.kt index 56e3fe6c1..ae2478339 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/extensions/DateExtensions.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/extensions/DateExtensions.kt @@ -10,6 +10,13 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -fun Date.toExpirationDateString(): String { - return SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(this) -} +fun Date.toExpirationDateString(): String = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(this) + +/** + * Parses an expiration date string in "yyyy-MM-dd 00:00:00" format into a millisecond timestamp + * representing the start of that day. + * + * @return The time in milliseconds since the epoch, or 0 if parsing fails. + */ +fun String.toExpirationDateLong(): Long = + SimpleDateFormat("yyyy-MM-dd 00:00:00", Locale.getDefault()).parse(this)?.time ?: 0L diff --git a/app/src/main/res/drawable/schedule_24px.xml b/app/src/main/res/drawable/schedule_24px.xml new file mode 100644 index 000000000..f69c9764e --- /dev/null +++ b/app/src/main/res/drawable/schedule_24px.xml @@ -0,0 +1,16 @@ + + + + diff --git a/app/src/main/res/layout/activity_note_share.xml b/app/src/main/res/layout/activity_note_share.xml index 3ba0f7a79..525fb7a9a 100644 --- a/app/src/main/res/layout/activity_note_share.xml +++ b/app/src/main/res/layout/activity_note_share.xml @@ -78,54 +78,63 @@ - - - - - + android:layout_marginHorizontal="@dimen/spacer_2x" + app:cardBackgroundColor="@color/grey600" + app:cardCornerRadius="@dimen/spacer_4x" + app:strokeWidth="0dp"> - - - + tools:visibility="visible"> + + + + + + + + - + + + - + android:layout_marginEnd="@dimen/spacer_1x"> + + + + + More Nextcloud Apps More Sharing + Share expires on %1$s + Dismiss