1 /* 2 * Copyright 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.appfunctions.schema.notes 18 19 import android.net.Uri 20 import androidx.annotation.RestrictTo 21 import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP 22 import androidx.appfunctions.AppFunctionContext 23 import androidx.appfunctions.AppFunctionOpenable 24 import androidx.appfunctions.AppFunctionSchemaDefinition 25 import androidx.appfunctions.schema.types.SetField 26 import java.time.LocalDateTime 27 28 // TODO(b/407951385): Expose schema version. 29 /** 30 * The category name of Notes related app functions. 31 * 32 * Example of apps that can support this category of schema include note taking apps. 33 * 34 * The category is used to search app functions related to notes, using 35 * [androidx.appfunctions.AppFunctionSearchSpec.schemaCategory]. 36 */ 37 public const val APP_FUNCTION_SCHEMA_CATEGORY_NOTES: String = "notes" 38 39 /** Finds [AppFunctionNote]s with the given search criteria specified in [Parameters]. */ 40 @AppFunctionSchemaDefinition( 41 name = "findNotes", 42 version = FindNotesAppFunction.SCHEMA_VERSION, 43 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 44 ) 45 public interface FindNotesAppFunction< 46 Parameters : FindNotesAppFunction.Parameters, 47 Response : FindNotesAppFunction.Response 48 > { 49 /** 50 * Finds notes with the given search criteria. 51 * 52 * The implementing app should throw an appropriate [androidx.appfunctions.AppFunctionException] 53 * in exceptional cases. 54 * 55 * @param appFunctionContext The AppFunction execution context. 56 * @param parameters The parameters for finding notes. 57 * @return The response including the list of notes that match the parameters, or an empty list 58 * if no match is found. 59 */ findNotesnull60 public suspend fun findNotes( 61 appFunctionContext: AppFunctionContext, 62 parameters: Parameters, 63 ): Response 64 65 /** The parameters for finding notes. */ 66 public interface Parameters { 67 /** 68 * The search query to be processed. A null value means to query all notes with the 69 * remaining parameters. 70 * 71 * This parameter is analogous to the caller typing a query into a search box. The app 72 * providing the app function has full control over how the query is interpreted and 73 * processed; for example by name matching or semantic analysis. 74 */ 75 public val query: String? 76 get() = null 77 78 /** 79 * The date/time on or after which a note must have been modified to be included in the 80 * results. 81 * 82 * Acts as a lower bound for filtering notes based on their modification timestamp. A `null` 83 * value means no lower bound is applied. 84 * 85 * If `modifiedAfter` is equal to `modifiedBefore`, an empty list will be returned. 86 * 87 * [androidx.appfunctions.AppFunctionInvalidArgumentException] should be thrown if 88 * `modifiedAfter` is specified and is after `modifiedBefore`. 89 */ 90 public val modifiedAfter: LocalDateTime? 91 get() = null 92 93 /** 94 * The date/time before which a note must have been modified to be included in the results. 95 * 96 * Acts as a strict upper bound for filtering notes based on their modification timestamp. A 97 * `null` value means no upper bound is applied. 98 * 99 * If `modifiedAfter` is equal to `modifiedBefore`, an empty list will be returned. 100 * 101 * [androidx.appfunctions.AppFunctionInvalidArgumentException] should be thrown if 102 * `modifiedAfter` is specified and is after `modifiedBefore`. 103 */ 104 public val modifiedBefore: LocalDateTime? 105 get() = null 106 } 107 108 /** The response including the list of notes that match the parameters. */ 109 public interface Response { 110 /** The list of notes that match the parameters, or an empty list if no match is found. */ 111 public val notes: List<AppFunctionNote> 112 } 113 114 public companion object { 115 /** Current schema version. */ 116 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 117 } 118 } 119 120 /** Creates an [AppFunctionNote] with the given parameters. */ 121 @AppFunctionSchemaDefinition( 122 name = "createNote", 123 version = CreateNoteAppFunction.SCHEMA_VERSION, 124 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 125 ) 126 public interface CreateNoteAppFunction< 127 Parameters : CreateNoteAppFunction.Parameters, 128 Response : CreateNoteAppFunction.Response 129 > { 130 /** 131 * Creates an [AppFunctionNote] with the given parameters. 132 * 133 * The implementing app should throw an appropriate subclass of 134 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 135 * 136 * @param appFunctionContext The AppFunction execution context. 137 * @param parameters The parameters for creating a note. 138 * @return The response including the created note. 139 */ createNotenull140 public suspend fun createNote( 141 appFunctionContext: AppFunctionContext, 142 parameters: Parameters, 143 ): Response 144 145 /** The parameters for creating a note. */ 146 public interface Parameters { 147 /** The title of the note. */ 148 public val title: String 149 /** The text content of the note. */ 150 public val content: String? 151 get() = null 152 153 /** The attachments of the note. */ 154 public val attachments: List<AppFunctionNote.Attachment> 155 get() = emptyList() 156 157 /** 158 * The ID of the group the note is in, if any else `null`. 159 * 160 * [androidx.appfunctions.AppFunctionElementNotFoundException] should be thrown when a group 161 * with the specified groupId doesn't exist. 162 */ 163 public val groupId: String? 164 get() = null 165 166 /** 167 * An optional UUID for this note provided by the caller. If provided, the caller can use 168 * this UUID as well as the returned [AppFunctionNote.id] to reference this specific note in 169 * subsequent requests, such as a request to update the note that was just created. 170 * 171 * To support [externalUuid], the application should maintain a mapping between the 172 * [externalUuid] and the internal id of this note. This allows the application to retrieve 173 * the correct note when the caller references it using the provided `externalUuid` in 174 * subsequent requests. 175 * 176 * If the `externalUuid` is not provided by the caller in the creation request, the 177 * application should expect subsequent requests from the caller to reference the note using 178 * the application generated [AppFunctionNote.id]. 179 */ 180 public val externalUuid: String? 181 get() = null 182 } 183 184 /** The response including the created note. */ 185 public interface Response { 186 /** The created note. */ 187 public val createdNote: AppFunctionNote 188 } 189 190 public companion object { 191 /** Current schema version. */ 192 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 193 } 194 } 195 196 /** Updates an existing [AppFunctionNote]. */ 197 @AppFunctionSchemaDefinition( 198 name = "updateNote", 199 version = UpdateNoteAppFunction.SCHEMA_VERSION, 200 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 201 ) 202 public interface UpdateNoteAppFunction< 203 Parameters : UpdateNoteAppFunction.Parameters, 204 Response : UpdateNoteAppFunction.Response 205 > { 206 /** 207 * Updates an existing [AppFunctionNote] with the given parameters. 208 * 209 * For each field in [Parameters], if the corresponding [SetField] is not null, the note's field 210 * will be updated. The value within the [SetField] will be used to update the original value. 211 * Fields with a null [SetField] will not be updated. 212 * 213 * The implementing app should throw an appropriate subclass of 214 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 215 * 216 * @param appFunctionContext The AppFunction execution context. 217 * @param parameters The parameters defining the note to update and the new values. 218 * @return The response including the updated note. 219 */ updateNotenull220 public suspend fun updateNote( 221 appFunctionContext: AppFunctionContext, 222 parameters: Parameters, 223 ): Response 224 225 /** The parameters for updating a note. */ 226 public interface Parameters { 227 /** 228 * The ID of the note to update. It can be the ID generated by the application 229 * ([AppFunctionNote.id]) or an external UUID 230 * ([CreateNoteAppFunction.Parameters.externalUuid]) provided by the caller during note 231 * creation. 232 */ 233 public val noteId: String 234 235 /** The new title for the note, if it should be updated. */ 236 public val title: SetField<String>? 237 get() = null 238 239 /** The new content for the note, if it should be updated. */ 240 public val content: SetField<String?>? 241 get() = null 242 243 /** The new attachments for the note, if it should be updated. */ 244 public val attachments: SetField<List<AppFunctionNote.Attachment>>? 245 get() = null 246 } 247 248 /** The response including the updated note. */ 249 public interface Response { 250 /** The updated note. */ 251 public val updatedNote: AppFunctionNote 252 } 253 254 public companion object { 255 /** Current schema version. */ 256 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 257 } 258 } 259 260 /** Deletes the notes with the given search criteria, defined by {@code parameters}. */ 261 @AppFunctionSchemaDefinition( 262 name = "deleteNotes", 263 version = DeleteNotesAppFunction.SCHEMA_VERSION, 264 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 265 ) 266 public interface DeleteNotesAppFunction< 267 Parameters : DeleteNotesAppFunction.Parameters, 268 Response : DeleteNotesAppFunction.Response 269 > { 270 /** 271 * Deletes the notes with the given search criteria and returns the IDs of the notes that were 272 * successfully deleted. 273 * 274 * The implementing app should throw an appropriate subclass of 275 * [androidx.appfunctions.AppFunctionException] in exceptional cases, except for failures in 276 * deleting individual noteId(s), which can be ignored when returning the 277 * [DeleteNotesAppFunction.Response]. 278 * 279 * @param appFunctionContext The AppFunction execution context. 280 * @param parameters The parameters defining the criteria of notes to delete. 281 * @return A list of successfully deleted note IDs. 282 */ deleteNotesnull283 public suspend fun deleteNotes( 284 appFunctionContext: AppFunctionContext, 285 parameters: Parameters, 286 ): Response 287 288 /** The parameters defining the criteria of notes to delete. */ 289 public interface Parameters { 290 /** The IDs of the notes to delete. */ 291 public val noteIds: List<String> 292 } 293 294 /** The response of delete notes request. */ 295 public interface Response { 296 /** A list of successfully deleted note IDs. */ 297 public val noteIds: List<String> 298 } 299 300 public companion object { 301 /** Current schema version. */ 302 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 303 } 304 } 305 306 /** Gets [AppFunctionNote]s with the given IDs. */ 307 @AppFunctionSchemaDefinition( 308 name = "getNotes", 309 version = GetNotesAppFunction.SCHEMA_VERSION, 310 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 311 ) 312 public interface GetNotesAppFunction< 313 Parameters : GetNotesAppFunction.Parameters, 314 Response : GetNotesAppFunction.Response 315 > { 316 /** 317 * Gets the notes with the given IDs. Returns only the notes found for the provided IDs. Does 318 * not throw if some IDs are not found. 319 * 320 * The implementing app should throw an appropriate subclass of 321 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 322 * 323 * @param appFunctionContext The AppFunction execution context. 324 * @param parameters The parameters defining which notes to get. 325 * @return The response including the list of notes that match the given IDs. 326 */ getNotesnull327 public suspend fun getNotes( 328 appFunctionContext: AppFunctionContext, 329 parameters: Parameters, 330 ): Response 331 332 /** The parameters defining the IDs of the notes to get. */ 333 public interface Parameters { 334 /** The IDs of the notes to get. */ 335 public val noteIds: List<String> 336 } 337 338 /** The response including the list of notes that match the given IDs. */ 339 public interface Response { 340 /** The list of notes that match the given IDs. */ 341 public val notes: List<AppFunctionNote> 342 } 343 344 public companion object { 345 /** Current schema version. */ 346 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 347 } 348 } 349 350 /** 351 * Shows the note with the given parameters. 352 * 353 * @param Parameters The parameters of the note to show. 354 * @param Response The response including the [AppFunctionOpenable] to show the note. 355 */ 356 @AppFunctionSchemaDefinition( 357 name = "showNote", 358 version = ShowNoteAppFunction.SCHEMA_VERSION, 359 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 360 ) 361 public interface ShowNoteAppFunction< 362 Parameters : ShowNoteAppFunction.Parameters, 363 Response : ShowNoteAppFunction.Response 364 > { 365 /** 366 * Shows the note with the given parameters. 367 * 368 * The implementing app should throw an appropriate subclass of 369 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 370 * 371 * @param appFunctionContext The AppFunction execution context. 372 * @param parameters The params of the note to show. 373 * @return The response including the intent to show the note. 374 */ showNotenull375 public suspend fun showNote( 376 appFunctionContext: AppFunctionContext, 377 parameters: Parameters 378 ): Response 379 380 /** The parameters for [showNote]. */ 381 public interface Parameters { 382 /** 383 * The [AppFunctionNote.id] of the note to show. 384 * 385 * [androidx.appfunctions.AppFunctionElementNotFoundException] should be thrown when a note 386 * with the specified noteId doesn't exist. 387 */ 388 public val noteId: String 389 } 390 391 /** The [AppFunctionOpenable] response for [showNote]. */ 392 public interface Response : AppFunctionOpenable 393 394 public companion object { 395 /** Current schema version. */ 396 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 397 } 398 } 399 400 /** Finds notes groups with the given search criteria. */ 401 @AppFunctionSchemaDefinition( 402 name = "findFolders", 403 version = FindNotesGroupsAppFunction.SCHEMA_VERSION, 404 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 405 ) 406 public interface FindNotesGroupsAppFunction< 407 Parameters : FindNotesGroupsAppFunction.Parameters, 408 Response : FindNotesGroupsAppFunction.Response 409 > { 410 /** 411 * Finds notes groups with the given search criteria. 412 * 413 * The implementing app should throw an appropriate subclass of 414 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 415 * 416 * @param appFunctionContext The AppFunction execution context. 417 * @param parameters The parameters for finding groups. 418 * @return The response including the list of groups that match the parameters, or an empty list 419 * if no match is found. 420 */ findNotesGroupsnull421 public suspend fun findNotesGroups( 422 appFunctionContext: AppFunctionContext, 423 parameters: Parameters, 424 ): Response 425 426 /** The parameters for finding groups. */ 427 public interface Parameters { 428 /** 429 * The query to search for groups. A null value means to query all groups. 430 * 431 * This parameter is analogous to the caller typing a query into a search box. The app 432 * providing the app function has full control over how the query is interpreted and 433 * processed; for example by name matching or semantic analysis. 434 */ 435 public val query: String? 436 get() = null 437 } 438 439 /** The response including the list of groups that match the parameters. */ 440 public interface Response { 441 /** The list of groups that match the parameters, or an empty list if no match is found. */ 442 public val groups: List<AppFunctionNotesGroup> 443 } 444 445 public companion object { 446 447 /** Current schema version. */ 448 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 449 } 450 } 451 452 /** Creates a group with the given parameters. */ 453 @AppFunctionSchemaDefinition( 454 name = "createFolder", 455 version = CreateNotesGroupAppFunction.SCHEMA_VERSION, 456 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 457 ) 458 public interface CreateNotesGroupAppFunction< 459 Parameters : CreateNotesGroupAppFunction.Parameters, 460 Response : CreateNotesGroupAppFunction.Response 461 > { 462 /** 463 * Creates a notes group with the given parameters. 464 * 465 * The implementing app should throw an appropriate subclass of 466 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 467 * 468 * @param appFunctionContext The AppFunction execution context. 469 * @param parameters The parameters for creating a group. 470 * @return The created group. 471 */ createNotesGroupnull472 public suspend fun createNotesGroup( 473 appFunctionContext: AppFunctionContext, 474 parameters: Parameters, 475 ): Response 476 477 /** The parameters for creating a group. */ 478 public interface Parameters { 479 /** The label of the group. */ 480 public val label: String 481 } 482 483 /** The response including the created group. */ 484 public interface Response { 485 /** The created group. */ 486 public val createdGroup: AppFunctionNotesGroup 487 } 488 489 public companion object { 490 491 /** Current schema version. */ 492 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 493 } 494 } 495 496 /** Deletes groups with the given parameters. */ 497 @AppFunctionSchemaDefinition( 498 name = "deleteFolders", 499 version = DeleteNotesGroupsAppFunction.SCHEMA_VERSION, 500 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 501 ) 502 public interface DeleteNotesGroupsAppFunction< 503 Parameters : DeleteNotesGroupsAppFunction.Parameters, 504 Response : DeleteNotesGroupsAppFunction.Response 505 > { 506 /** 507 * Deletes notes groups with the given parameters and returns the IDs of the groups that were 508 * successfully deleted. 509 * 510 * The implementing app should throw an appropriate subclass of 511 * [androidx.appfunctions.AppFunctionException] in exceptional cases, except for failures in 512 * deleting individual groupId(s), which can be ignored when returning the 513 * [DeleteNotesGroupsAppFunction.Response]. 514 * 515 * @param appFunctionContext The AppFunction execution context. 516 * @param parameters The parameters of the groups to delete. 517 * @return The response including the list of successfully deleted group IDs. 518 */ deleteNotesGroupsnull519 public suspend fun deleteNotesGroups( 520 appFunctionContext: AppFunctionContext, 521 parameters: Parameters, 522 ): Response 523 524 /** The parameters of the groups to delete. */ 525 public interface Parameters { 526 /** The [AppFunctionNotesGroup.id] of the groups to delete. */ 527 public val groupIds: List<String> 528 } 529 530 /** The response including the list of successfully deleted group IDs. */ 531 public interface Response { 532 /** The IDs of the deleted groups. */ 533 public val groupIds: List<String> 534 } 535 536 public companion object { 537 538 /** Current schema version. */ 539 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 540 } 541 } 542 543 /** Updates an existing [AppFunctionNotesGroup]. */ 544 @AppFunctionSchemaDefinition( 545 name = "updateFolder", 546 version = UpdateNotesGroupAppFunction.SCHEMA_VERSION, 547 category = APP_FUNCTION_SCHEMA_CATEGORY_NOTES 548 ) 549 public interface UpdateNotesGroupAppFunction< 550 Parameters : UpdateNotesGroupAppFunction.Parameters, 551 Response : UpdateNotesGroupAppFunction.Response 552 > { 553 /** 554 * Updates an existing [AppFunctionNotesGroup] with the given parameters. 555 * 556 * For each field in [Parameters], if the corresponding [SetField] is not null, the note group's 557 * field will be updated. The value within the [SetField] will be used to update the original 558 * value. Fields with a null [SetField] will not be updated. 559 * 560 * The implementing app should throw an appropriate subclass of 561 * [androidx.appfunctions.AppFunctionException] in exceptional cases. 562 * 563 * @param appFunctionContext The AppFunction execution context. 564 * @param parameters The parameters defining the notes group to update and the new values. 565 * @return The response including the updated notes group. 566 */ updateNotesGroupnull567 public suspend fun updateNotesGroup( 568 appFunctionContext: AppFunctionContext, 569 parameters: Parameters, 570 ): Response 571 572 /** The parameters for updating a notes group. */ 573 public interface Parameters { 574 /** 575 * The ID of the notes group to update. 576 * 577 * [androidx.appfunctions.AppFunctionElementNotFoundException] should be thrown when a group 578 * with the specified notesGroupId doesn't exist. 579 */ 580 public val notesGroupId: String 581 582 /** The new label for the group, if it should be updated. */ 583 public val label: SetField<String>? 584 get() = null 585 } 586 587 /** The response including the updated notes group. */ 588 public interface Response { 589 /** The updated notes group. */ 590 public val updatedNotesGroup: AppFunctionNotesGroup 591 } 592 593 public companion object { 594 /** Current schema version. */ 595 @RestrictTo(LIBRARY_GROUP) internal const val SCHEMA_VERSION: Int = 2 596 } 597 } 598 599 /** A note entity. */ 600 public interface AppFunctionNote { 601 /** The ID of the note. */ 602 public val id: String 603 604 /** The title of the note. */ 605 public val title: String 606 607 /** The content of the note. */ 608 public val content: String? 609 get() = null 610 611 /** The attachments of the note. */ 612 public val attachments: List<Attachment> 613 get() = emptyList() 614 615 /** An attached file. */ 616 public interface Attachment { 617 /** 618 * The URI of the attached file. 619 * 620 * When providing an [Uri] to another app, that app must be granted URI permission using 621 * [android.content.Context.grantUriPermission] to the receiving app. 622 * 623 * The providing app should also consider revoking the URI permission by using 624 * [android.content.Context.revokeUriPermission] after a certain time period. 625 */ 626 public val uri: Uri 627 628 /** The display name of the attached file. */ 629 public val displayName: String 630 631 /** The MIME type of the attached file. Format defined in RFC 6838. */ 632 public val mimeType: String? 633 get() = null 634 } 635 636 /** The ID of the group the note is in, if any else `null`. */ 637 public val groupId: String? 638 get() = null 639 } 640 641 /** Represents a group used to organize notes. */ 642 public interface AppFunctionNotesGroup { 643 /** The ID of the group. */ 644 public val id: String 645 /** The label of the group. */ 646 public val label: String 647 } 648