Simplify Iris app initialization and task updates
This commit is contained in:
1 parent
b5666cdef9
commit
166bac2a93
25 files changed
+330
-282
No files matched your search
+32
-13
@@ -9,13 +9,15 @@ use syn::{
|
||||
spanned::Spanned,
|
||||
};
|
||||
|
||||
/// Marks the factory called when Android creates an Iris view.
|
||||
/// Marks the initializer called when Android creates an Iris view.
|
||||
///
|
||||
/// An attribute is necessary here because the Android loader requires one
|
||||
/// exported `JNI_OnLoad` symbol and `android-view` requires a plain function
|
||||
/// pointer monomorphized for the returned application state. The generated
|
||||
/// linker and JNI glue is Android-gated; the annotated function therefore
|
||||
/// does not need its own `cfg` attribute.
|
||||
/// pointer monomorphized for the application state. A function returning a
|
||||
/// custom state remains its factory; a function with no return value receives
|
||||
/// `&mut AndroidUiState` and uses that state directly. The generated linker and
|
||||
/// JNI glue is Android-gated; the annotated function therefore does not need
|
||||
/// its own `cfg` attribute.
|
||||
#[proc_macro_attribute]
|
||||
pub fn app_init(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
if !args.is_empty() {
|
||||
@@ -29,13 +31,9 @@ pub fn app_init(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
let function = parse_macro_input!(item as ItemFn);
|
||||
let name = &function.sig.ident;
|
||||
let ReturnType::Type(_, state) = &function.sig.output else {
|
||||
return Error::new(
|
||||
function.sig.output.span(),
|
||||
"an app_init function must return its application state",
|
||||
)
|
||||
.into_compile_error()
|
||||
.into();
|
||||
let (state, direct_initializer): (Type, bool) = match &function.sig.output {
|
||||
ReturnType::Default => (parse_quote!(::iris::android::AndroidUiState), true),
|
||||
ReturnType::Type(_, state) => ((**state).clone(), false),
|
||||
};
|
||||
if function.sig.inputs.len() != 2
|
||||
|| function
|
||||
@@ -46,7 +44,7 @@ pub fn app_init(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
{
|
||||
return Error::new(
|
||||
function.sig.inputs.span(),
|
||||
"an app_init function takes AndroidUiState and &mut State::Resources",
|
||||
"an app_init function takes UI state and resources",
|
||||
)
|
||||
.into_compile_error()
|
||||
.into();
|
||||
@@ -64,6 +62,25 @@ pub fn app_init(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
.into();
|
||||
}
|
||||
|
||||
let factory = if direct_initializer {
|
||||
quote! {
|
||||
fn init(
|
||||
mut ui_state: ::iris::android::AndroidUiState,
|
||||
rsc: &mut <#state as ::iris::android::AndroidAppState>::Resources,
|
||||
) -> #state {
|
||||
super::#name(&mut ui_state, rsc);
|
||||
ui_state
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
let create = if direct_initializer {
|
||||
quote! { init }
|
||||
} else {
|
||||
quote! { super::#name }
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[cfg(target_os = "android")]
|
||||
#function
|
||||
@@ -72,12 +89,14 @@ pub fn app_init(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
mod __iris_android_app {
|
||||
use super::*;
|
||||
|
||||
#factory
|
||||
|
||||
extern "system" fn new_view_peer<'local>(
|
||||
env: ::iris::android::__private::JNIEnv<'local>,
|
||||
view: ::iris::android::__private::View<'local>,
|
||||
context: ::iris::android::__private::Context<'local>,
|
||||
) -> ::iris::android::__private::JLong {
|
||||
::iris::android::new_peer::<#state>(env, view, context, super::#name)
|
||||
::iris::android::new_peer::<#state>(env, view, context, #create)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
|
||||
Reference in new issue
Block a user