Skip to main content

cranpose_services/
lib.rs

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