1 /* 2 * Copyright 2024 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 com.android.photopicker.core.features 18 19 import com.android.photopicker.core.configuration.PhotopickerConfiguration 20 import com.android.photopicker.core.events.Event 21 import com.android.photopicker.core.events.RegisteredEventClass 22 23 /** 24 * The base feature interface, that exposes hooks from the [FeatureManager] that is available to all 25 * features. It's unlikely that features will want to implement this directly, but rather implement 26 * a different interface, such as [PhotopickerUiFeature] which inherits from the base interface. 27 */ 28 interface PhotopickerFeature { 29 30 /** 31 * Features must claim a [FeatureToken]. This is used to identify calls the feature makes such 32 * as dispatching events (to ensure the feature has registered for these events). This must be 33 * unique for any given runtime configuration of enabled features. Multiple features may claim 34 * the same token, but they can never be enabled in the same configuration, or an 35 * [IllegalStateException] will be thrown during initialization. 36 */ 37 val token: String 38 39 /** 40 * Establishes the contract of Events that this feature requires from outside dependencies. Any 41 * [Event] that is listened to inside any codepath this feature encapsulates should be 42 * registered in this set. 43 * 44 * In the event the feature has indicated it should be enabled (in its Registration check) and 45 * it's set of consumed events is not fulfilled by the global events produced this will cause a 46 * RuntimeException if [PhotopickerConfiguration.isDeviceDebuggable] is true. 47 * 48 * For non debuggable devices, the error is not thrown to avoid crashes if possible, but this 49 * should be considered a state which should be avoided at all costs. 50 */ 51 val eventsConsumed: Set<RegisteredEventClass> 52 53 /** 54 * Establishes the contract of Events that this Feature produces. 55 * 56 * Any [Event] that is dispatched inside any codepath this feature encapsulates should be 57 * registered in the returned set. 58 * 59 * The events produced here is used to compute the list of globally produced events to check if 60 * all required events in a runtime configuration are produceable. Note: This does not mean that 61 * events WILL be produced, as that may be user-interaction dependant, but this helps to catch 62 * implicit or undeclared dependencies between features that rely on the Event bus. 63 * 64 * If an event is dispatched in a feature which is not present in its eventsProduced registry, 65 * this will trigger a RuntimeException when [PhotopickerConfiguration.isDeviceDebuggable] is 66 * true, and a warning will be logged otherwise. 67 */ 68 val eventsProduced: Set<RegisteredEventClass> 69 70 /** 71 * Notification hook that the [FeatureManager] is about to emit a new configuration, and 72 * reinitialize the active Feature set. 73 * 74 * It is highly likely that shortly after this call completes the current instance of this class 75 * will be de-referenced and (potentially) be re-created if the Registration check still 76 * indicates it should be enabled with the new configuration. 77 * 78 * The UI tree will be re-composed shortly after, and persistent state should be saved in 79 * associated view models to avoid state loss. 80 */ onConfigurationChangednull81 fun onConfigurationChanged(config: PhotopickerConfiguration) {} 82 } 83