Skip to main content

cranpose_services/
lib.rs

1//! Multiplatform service abstractions used by Cranpose applications.
2
3#[cfg(test)]
4use cranpose_core::{Composition, MemoryApplier, location_key};
5
6pub mod accessibility_options;
7pub mod accessibility_state;
8pub mod app_info;
9pub mod app_update;
10pub mod async_io;
11pub mod audio;
12pub mod background;
13pub mod bundled_assets;
14pub mod camera;
15pub mod content;
16pub mod device_info;
17pub mod file_picker;
18#[cfg(not(target_arch = "wasm32"))]
19pub mod github_release_updater;
20pub mod haptics;
21pub mod host;
22pub mod host_surface;
23pub mod http;
24pub mod image_picker;
25pub mod incoming_share;
26pub mod launch_args;
27pub mod launcher;
28pub mod media;
29pub mod memory_pressure;
30pub mod navigation;
31pub mod network_status;
32pub mod notifier;
33#[cfg(not(target_arch = "wasm32"))]
34pub mod peer;
35pub mod power;
36pub mod preferences;
37pub mod purchases;
38mod registry;
39pub mod share_sheet;
40pub mod theme;
41pub mod uri_handler;
42pub mod writable_folder;
43
44pub use accessibility_options::{
45    AccessibilityOptions, ProvideAccessibilityOptions, local_accessibility_options,
46    platform_accessibility_options, set_platform_accessibility_options,
47};
48pub use accessibility_state::{
49    AccessibilityState, ProvideAccessibilityState, local_accessibility_state,
50    platform_accessibility_state, set_platform_accessibility_state,
51};
52pub use app_info::{
53    AppInfo, AppInfoRef, app_info, build_version, clear_platform_app_info, set_platform_app_info,
54    version_name,
55};
56pub use app_update::{
57    AppUpdateCapabilities, AppUpdateError, AppUpdateObserver, AppUpdateStatus, AppUpdater,
58    AppUpdaterRef, DigestAlgorithm, DigestVerifier, GitHubReleaseUpdate, PackageDigest,
59    UpdatePackage, app_update_capabilities, app_update_checks_supported, app_update_status,
60    app_updates_supported, check_for_app_update, clear_platform_app_updater, install_app_update,
61    observe_app_update_status, set_app_update_status, set_platform_app_updater, sha256_hex,
62    verify_package,
63};
64pub use async_io::{ChunkChannel, ChunkNext, ChunkStream, MAX_PENDING_CHUNKS, Signal, SignalWait};
65pub use audio::{
66    AudioBus, AudioClip, AudioError, AudioPlayer, AudioPlayerRef, NoopAudioPlayer, PlaybackParams,
67    ProvideAudio, SoundBank, SoundBankEntry, SoundBankFailure, SoundId, SoundSpec, VoiceId,
68    clear_platform_audio, default_audio, local_audio, rememberSoundBank, set_platform_audio,
69};
70pub use background::{
71    BackgroundActivity, BackgroundActivityRef, BackgroundWorkLease, acquire_background_work,
72    background_active, background_activity, clear_platform_background_activity,
73    set_platform_background_activity,
74};
75#[cfg(not(target_arch = "wasm32"))]
76pub use bundled_assets::{
77    BundledAssetEntry, BundledAssetInstallOutcome, BundledAssetInstallSpec,
78    install_bundled_asset_set,
79};
80pub use bundled_assets::{
81    BundledAssetError, BundledAssetReader, BundledAssets, BundledAssetsRef, StreamingAssetReader,
82    bundled_assets, clear_platform_bundled_assets, set_platform_bundled_assets,
83};
84pub use camera::{
85    Camera, CameraError, CameraFrame, CameraLens, CameraLenses, CameraObserver, CameraRef,
86    CameraState, CameraStill, FlashMode, FrameFormat, LensFacing, UprightRgba, camera,
87    camera_lenses, camera_state, camera_supported, capture_camera_still, clear_platform_camera,
88    dropped_camera_frames, latest_camera_frame, observe_camera_frames, observe_camera_lenses,
89    observe_camera_state, observe_camera_stills, publish_camera_frame, publish_camera_lenses,
90    publish_camera_state, publish_camera_still, record_dropped_camera_frame, rememberCameraFrames,
91    rememberCameraLenses, rememberCameraState, rememberCameraStills, request_camera_still,
92    set_platform_camera, start_camera, stop_camera,
93};
94pub use content::{
95    BytesContent, Content, ContentChannel, ContentEntry, ContentError, ContentFolder,
96    ContentFolderRef, ContentFuture, ContentHandle, ContentMetadata, ContentReader,
97    ContentReaderRef, ContentResolver, ContentResolverRef, ContentSink, ContentSinkRef,
98    ContentStream, ContentStreamRef, DEFAULT_CHUNK_LEN, ReadyFolder,
99    clear_platform_content_resolver, collect_stream, drain_reader, folder_files, percent_decode,
100    percent_decode_lossy, resolve_content, set_platform_content_resolver, write_all,
101};
102#[cfg(not(target_arch = "wasm32"))]
103pub use content::{FileContent, FileFolder, FileSink, file_content, file_folder};
104pub use device_info::{
105    DeviceInfo, DeviceInfoRef, clear_platform_device_info, device_info, release_free_memory,
106    set_platform_device_info,
107};
108pub use file_picker::{
109    FileFilter, FilePicker, FilePickerError, FilePickerOptions, FilePickerRef, PickerFuture,
110    ProvideFilePicker, RecoveredPick, SaveDocumentRequest, clear_platform_file_picker,
111    default_file_picker, local_file_picker, set_platform_file_picker,
112};
113#[cfg(not(target_arch = "wasm32"))]
114pub use github_release_updater::GitHubAppUpdater;
115pub use haptics::{
116    HapticEffect, HapticError, HapticFeedback, HapticPattern, Haptics, HapticsRef, ProvideHaptics,
117    clear_platform_haptics, default_haptics, local_haptics, set_platform_haptics,
118};
119pub use host::{
120    DEFAULT_DURABLE_SAVE_DEADLINE, DurableSaveEffect, DurableSaveOutcome, DurableSaveRegistration,
121    HostController, HostControllerRef, LifecycleEvent, LifecycleObserver, LifecycleState,
122    PlatformDirectories, PlatformDirectoryError, ProvideLifecycle, application_directories,
123    application_id, background_app, clear_application_id, clear_host_controller,
124    current_lifecycle_state, dispatch_lifecycle, dispatch_lifecycle_state, exit_app,
125    host_controller, local_lifecycle_state, observe_lifecycle, register_durable_save,
126    rememberLifecycleEvents, rememberLifecycleState, set_application_id, set_host_controller,
127    set_keep_screen_on,
128};
129#[cfg(not(target_arch = "wasm32"))]
130pub use host::{durable_save_deadline, run_durable_saves};
131pub use host_surface::{
132    HostSurface, HostSurfaceObserver, HostSurfaceRef, HostSurfaceSize, ResizeRefused,
133    clear_platform_host_surface, host_surface, host_surface_size, observe_host_surface_size,
134    publish_host_surface_size, rememberHostSurfaceSize, request_host_surface_size,
135    set_platform_host_surface,
136};
137pub use http::{
138    BytesBody, HttpBody, HttpBodyRef, HttpClient, HttpClientRef, HttpControl, HttpError,
139    HttpFuture, HttpMethod, HttpProgress, HttpRequest, HttpResponse, ProgressHandler, StubAnswer,
140    StubHttpClient, default_http_client, http_body_ref, local_http_client, map_ordered_concurrent,
141};
142pub use image_picker::{
143    IMAGE_EXTENSIONS, ImagePicker, ImagePickerError, ImagePickerRef, ImageSource,
144    ProvideImagePicker, clear_platform_image_picker, default_image_picker, local_image_picker,
145    set_platform_image_picker,
146};
147pub use incoming_share::{
148    IncomingContent, IncomingContentObserver, IncomingSource, clear_incoming_content,
149    observe_incoming_content, publish_incoming_content, rememberIncomingContent,
150};
151pub use launch_args::{
152    LaunchArgValue, LaunchArgs, LaunchArgsRef, ProvideLaunchArgs, clear_platform_launch_args,
153    is_debuggable, isDebuggable, launch_args, launch_args_from_command_line, local_launch_args,
154    set_platform_launch_args,
155};
156pub use launcher::{
157    LauncherResult, OpenFileLauncher, OpenFilesLauncher, OpenFolderLauncher, SaveDocumentLauncher,
158    WritableFolderLauncher, clear_launcher_state, rememberOpenFileLauncher,
159    rememberOpenFilesLauncher, rememberOpenFolderLauncher, rememberSaveDocumentLauncher,
160    rememberWritableFolderLauncher,
161};
162pub use media::{
163    AudioFocus, DUCKED_GAIN, EqualizerBand, EqualizerSettings, MediaArtwork, MediaCapabilities,
164    MediaCommand, MediaError, MediaItem, MediaMetadata, MediaObserver, MediaPlayer, MediaPlayerRef,
165    MediaSamples, MediaSourceHandle, MediaSourceOpener, MediaSourceOpenerRef,
166    OCTAVE_BAND_CENTERS_HZ, PlaybackProgress, PlaybackState, audio_focus,
167    clear_platform_media_player, clear_platform_media_source_opener, current_media_item,
168    dropped_media_samples, latest_media_samples, media_capabilities, media_equalizer,
169    media_equalizer_bands, media_playback_supported, media_player, media_volume,
170    observe_audio_focus, observe_media_commands, observe_media_samples, observe_playback_progress,
171    observe_playback_state, octave_equalizer_bands, open_media, open_media_source, path_from_uri,
172    pause_media, play_media, playback_progress, playback_state, probe_media_duration,
173    publish_audio_focus, publish_media_command, publish_media_samples, publish_playback_progress,
174    publish_playback_state, record_dropped_media_samples, rememberAudioFocus,
175    rememberMediaCommands, rememberMediaSamples, rememberPlaybackProgress, rememberPlaybackState,
176    seek_media, seek_media_fraction, set_media_analysis_enabled, set_media_equalizer,
177    set_media_looping, set_media_metadata, set_media_speed, set_media_volume,
178    set_platform_media_player, set_platform_media_source_opener, stop_media, toggle_media,
179    uri_for_path,
180};
181pub use memory_pressure::{
182    MemoryPressure, MemoryPressureObserver, observe_memory_pressure, publish_memory_pressure,
183    rememberMemoryPressure,
184};
185pub use navigation::{
186    BackRequestObserver, back_interception_enabled, exit_requested, observe_back_requests,
187    push_back_request, request_exit, set_back_interception, take_back_requests, take_exit_request,
188};
189pub use network_status::{
190    NetworkMonitor, NetworkMonitorRef, NetworkStatus, clear_platform_network_monitor,
191    network_monitor, network_status, set_platform_network_monitor,
192};
193pub use notifier::{
194    Notifier, NotifierRef, NotifyRequest, ProvideNotifier, clear_platform_notifier,
195    default_notifier, local_notifier, push_notification_deeplink, set_platform_notifier,
196    take_notification_deeplink,
197};
198#[cfg(not(target_arch = "wasm32"))]
199pub use peer::{
200    ByteSource, BytesSource, FetchResult, PeerError, PeerServer, SourceResolver, content_length,
201    fetch_range, fetch_to_writer,
202};
203pub use power::{
204    BatteryStatus, PowerCapabilities, PowerMonitor, PowerMonitorRef, PowerObserverRegistration,
205    PowerReading, PowerState, ThermalState, clear_platform_power_monitor, observe_power_state,
206    power_capabilities, power_monitor, power_state, publish_power_state, rememberPowerState,
207    set_platform_power_monitor,
208};
209#[cfg(all(target_arch = "wasm32", feature = "preferences-web"))]
210pub use preferences::BrowserPreferences;
211#[cfg(not(target_arch = "wasm32"))]
212pub use preferences::FilePreferences;
213pub use preferences::{
214    MemoryPreferences, PreferencesError, PreferencesRef, PreferencesStore, Saver,
215    clear_platform_preferences, preferences, rememberSaveable, set_platform_preferences,
216};
217pub use purchases::{
218    Product, PurchaseEvent, Purchases, PurchasesRef, StoreObserver, StorePhase, StoreState,
219    clear_platform_purchases, note_store_news, observe_store_news, purchases,
220    rememberPurchaseEvents, rememberStoreState, set_platform_purchases, store_available,
221    store_state,
222};
223pub use share_sheet::{
224    ProvideShareSheet, ShareContent, ShareError, ShareSheet, ShareSheetRef,
225    clear_platform_share_sheet, default_share_sheet, local_share_sheet, set_platform_share_sheet,
226};
227pub use theme::{
228    ProvideSystemTheme, SystemTheme, clear_platform_system_theme, default_system_theme,
229    isSystemInDarkTheme, local_system_theme, set_platform_system_theme,
230};
231pub use uri_handler::{
232    ProvideUriHandler, UriHandler, UriHandlerError, UriHandlerRef, clear_platform_uri_handler,
233    default_uri_handler, local_uri_handler, set_platform_uri_handler,
234};
235pub use writable_folder::{
236    FolderEntry, FolderError, FolderReader, FolderWriter, WritableFolderStore,
237    WritableFolderStoreRef, open_writable_folder, set_writable_folder_store_factory,
238};
239
240#[cfg(test)]
241pub(crate) type TestComposition = Composition<MemoryApplier>;
242
243#[cfg(test)]
244pub(crate) fn test_scratch_dir(tag: &str) -> std::path::PathBuf {
245    cranpose_core::test_scratch_dir(env!("CARGO_MANIFEST_DIR"), tag)
246}
247
248#[cfg(test)]
249pub(crate) fn run_test_composition(build: impl FnMut()) -> TestComposition {
250    let mut composition = Composition::new(MemoryApplier::new());
251    composition
252        .render(location_key(file!(), line!(), column!()), build)
253        .expect("initial render succeeds");
254    composition
255}
256
257/// What a composable read while a test composition ran once, or `None` when
258/// the read never ran.
259#[cfg(test)]
260pub(crate) fn captured_in_composition<T: Copy + 'static>(
261    read: impl Fn() -> T + 'static,
262) -> Option<T> {
263    let captured = std::rc::Rc::new(std::cell::Cell::new(None));
264    let sink = std::rc::Rc::clone(&captured);
265    run_test_composition(move || sink.set(Some(read())));
266    captured.get()
267}