diff --git a/bindings/electron/src/index.d.ts b/bindings/electron/src/index.d.ts index b60c68a9e62..0d8937cfc6a 100644 --- a/bindings/electron/src/index.d.ts +++ b/bindings/electron/src/index.d.ts @@ -199,6 +199,12 @@ export interface StartedWorkspaceInfo { } +export interface Tos { + perLocaleUrls: Map + updatedOn: number +} + + export interface UserClaimFinalizeInfo { handle: number } @@ -454,6 +460,30 @@ export type ClaimerRetrieveInfoError = | ClaimerRetrieveInfoErrorOffline +// ClientAcceptTosError +export interface ClientAcceptTosErrorInternal { + tag: "Internal" + error: string +} +export interface ClientAcceptTosErrorNoTos { + tag: "NoTos" + error: string +} +export interface ClientAcceptTosErrorOffline { + tag: "Offline" + error: string +} +export interface ClientAcceptTosErrorTosMismatch { + tag: "TosMismatch" + error: string +} +export type ClientAcceptTosError = + | ClientAcceptTosErrorInternal + | ClientAcceptTosErrorNoTos + | ClientAcceptTosErrorOffline + | ClientAcceptTosErrorTosMismatch + + // ClientCancelInvitationError export interface ClientCancelInvitationErrorAlreadyDeleted { tag: "AlreadyDeleted" @@ -529,6 +559,9 @@ export interface ClientEventInvitationChanged { token: string status: InvitationStatus } +export interface ClientEventMustAcceptTos { + tag: "MustAcceptTos" +} export interface ClientEventOffline { tag: "Offline" } @@ -595,6 +628,7 @@ export type ClientEvent = | ClientEventExpiredOrganization | ClientEventIncompatibleServer | ClientEventInvitationChanged + | ClientEventMustAcceptTos | ClientEventOffline | ClientEventOnline | ClientEventPing @@ -611,6 +645,25 @@ export type ClientEvent = | ClientEventWorkspacesSelfListChanged +// ClientGetTosError +export interface ClientGetTosErrorInternal { + tag: "Internal" + error: string +} +export interface ClientGetTosErrorNoTos { + tag: "NoTos" + error: string +} +export interface ClientGetTosErrorOffline { + tag: "Offline" + error: string +} +export type ClientGetTosError = + | ClientGetTosErrorInternal + | ClientGetTosErrorNoTos + | ClientGetTosErrorOffline + + // ClientGetUserDeviceError export interface ClientGetUserDeviceErrorInternal { tag: "Internal" @@ -2116,6 +2169,10 @@ export function claimerUserInitialDoWaitPeer( canceller: number, handle: number ): Promise> +export function clientAcceptTos( + client: number, + tos_updated_on: number +): Promise> export function clientCancelInvitation( client: number, token: string @@ -2129,6 +2186,9 @@ export function clientCreateWorkspace( client: number, name: string ): Promise> +export function clientGetTos( + client: number +): Promise> export function clientGetUserDevice( client: number, device: string diff --git a/bindings/electron/src/meths.rs b/bindings/electron/src/meths.rs index e405642bafa..38752bee64f 100644 --- a/bindings/electron/src/meths.rs +++ b/bindings/electron/src/meths.rs @@ -1649,6 +1649,105 @@ fn struct_started_workspace_info_rs_to_js<'a>( Ok(js_obj) } +// Tos + +#[allow(dead_code)] +fn struct_tos_js_to_rs<'a>( + cx: &mut impl Context<'a>, + obj: Handle<'a, JsObject>, +) -> NeonResult { + let per_locale_urls = { + let js_val: Handle = obj.get(cx, "perLocaleUrls")?; + { + let mut d = std::collections::HashMap::with_capacity( + js_val.get::(cx, "size")?.value(cx) as usize, + ); + + let js_keys = js_val + .call_method_with(cx, "keys")? + .apply::(cx)?; + let js_values = js_val + .call_method_with(cx, "values")? + .apply::(cx)?; + let js_keys_next_cb = js_keys.call_method_with(cx, "next")?; + let js_values_next_cb = js_values.call_method_with(cx, "next")?; + + loop { + let next_js_key = js_keys_next_cb.apply::(cx)?; + let next_js_value = js_values_next_cb.apply::(cx)?; + + let keys_done = next_js_key.get::(cx, "done")?.value(cx); + let values_done = next_js_value.get::(cx, "done")?.value(cx); + match (keys_done, values_done) { + (true, true) => break, + (false, false) => (), + _ => unreachable!(), + } + + let js_key = next_js_key.get::(cx, "value")?; + let js_value = next_js_value.get::(cx, "value")?; + + let key = js_key.value(cx); + let value = js_value.value(cx); + d.insert(key, value); + } + d + } + }; + let updated_on = { + let js_val: Handle = obj.get(cx, "updatedOn")?; + { + let v = js_val.value(cx); + let custom_from_rs_f64 = |n: f64| -> Result<_, &'static str> { + libparsec::DateTime::from_timestamp_micros((n * 1_000_000f64) as i64) + .map_err(|_| "Out-of-bound datetime") + }; + match custom_from_rs_f64(v) { + Ok(val) => val, + Err(err) => return cx.throw_type_error(err), + } + } + }; + Ok(libparsec::Tos { + per_locale_urls, + updated_on, + }) +} + +#[allow(dead_code)] +fn struct_tos_rs_to_js<'a>( + cx: &mut impl Context<'a>, + rs_obj: libparsec::Tos, +) -> NeonResult> { + let js_obj = cx.empty_object(); + let js_per_locale_urls = { + let new_map_code = (cx).string("new Map()"); + let js_map = neon::reflect::eval(cx, new_map_code)?.downcast_or_throw::(cx)?; + for (key, value) in rs_obj.per_locale_urls.into_iter() { + let js_key = JsString::try_new(cx, key).or_throw(cx)?; + let js_value = JsString::try_new(cx, value).or_throw(cx)?; + js_map + .call_method_with(cx, "set")? + .arg(js_key) + .arg(js_value) + .exec(cx)?; + } + js_map + }; + js_obj.set(cx, "perLocaleUrls", js_per_locale_urls)?; + let js_updated_on = JsNumber::new(cx, { + let custom_to_rs_f64 = |dt: libparsec::DateTime| -> Result { + Ok((dt.as_timestamp_micros() as f64) / 1_000_000f64) + }; + match custom_to_rs_f64(rs_obj.updated_on) { + Ok(ok) => ok, + Err(err) => return cx.throw_type_error(err), + } + }); + js_obj.set(cx, "updatedOn", js_updated_on)?; + Ok(js_obj) +} + // UserClaimFinalizeInfo #[allow(dead_code)] @@ -2754,6 +2853,37 @@ fn variant_claimer_retrieve_info_error_rs_to_js<'a>( Ok(js_obj) } +// ClientAcceptTosError + +#[allow(dead_code)] +fn variant_client_accept_tos_error_rs_to_js<'a>( + cx: &mut impl Context<'a>, + rs_obj: libparsec::ClientAcceptTosError, +) -> NeonResult> { + let js_obj = cx.empty_object(); + let js_display = JsString::try_new(cx, &rs_obj.to_string()).or_throw(cx)?; + js_obj.set(cx, "error", js_display)?; + match rs_obj { + libparsec::ClientAcceptTosError::Internal { .. } => { + let js_tag = JsString::try_new(cx, "ClientAcceptTosErrorInternal").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + libparsec::ClientAcceptTosError::NoTos { .. } => { + let js_tag = JsString::try_new(cx, "ClientAcceptTosErrorNoTos").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + libparsec::ClientAcceptTosError::Offline { .. } => { + let js_tag = JsString::try_new(cx, "ClientAcceptTosErrorOffline").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + libparsec::ClientAcceptTosError::TosMismatch { .. } => { + let js_tag = JsString::try_new(cx, "ClientAcceptTosErrorTosMismatch").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + } + Ok(js_obj) +} + // ClientCancelInvitationError #[allow(dead_code)] @@ -2889,6 +3019,7 @@ fn variant_client_event_js_to_rs<'a>( }; Ok(libparsec::ClientEvent::InvitationChanged { token, status }) } + "ClientEventMustAcceptTos" => Ok(libparsec::ClientEvent::MustAcceptTos {}), "ClientEventOffline" => Ok(libparsec::ClientEvent::Offline {}), "ClientEventOnline" => Ok(libparsec::ClientEvent::Online {}), "ClientEventPing" => { @@ -3189,6 +3320,10 @@ fn variant_client_event_rs_to_js<'a>( JsString::try_new(cx, enum_invitation_status_rs_to_js(status)).or_throw(cx)?; js_obj.set(cx, "status", js_status)?; } + libparsec::ClientEvent::MustAcceptTos { .. } => { + let js_tag = JsString::try_new(cx, "ClientEventMustAcceptTos").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } libparsec::ClientEvent::Offline { .. } => { let js_tag = JsString::try_new(cx, "ClientEventOffline").or_throw(cx)?; js_obj.set(cx, "tag", js_tag)?; @@ -3441,6 +3576,33 @@ fn variant_client_event_rs_to_js<'a>( Ok(js_obj) } +// ClientGetTosError + +#[allow(dead_code)] +fn variant_client_get_tos_error_rs_to_js<'a>( + cx: &mut impl Context<'a>, + rs_obj: libparsec::ClientGetTosError, +) -> NeonResult> { + let js_obj = cx.empty_object(); + let js_display = JsString::try_new(cx, &rs_obj.to_string()).or_throw(cx)?; + js_obj.set(cx, "error", js_display)?; + match rs_obj { + libparsec::ClientGetTosError::Internal { .. } => { + let js_tag = JsString::try_new(cx, "ClientGetTosErrorInternal").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + libparsec::ClientGetTosError::NoTos { .. } => { + let js_tag = JsString::try_new(cx, "ClientGetTosErrorNoTos").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + libparsec::ClientGetTosError::Offline { .. } => { + let js_tag = JsString::try_new(cx, "ClientGetTosErrorOffline").or_throw(cx)?; + js_obj.set(cx, "tag", js_tag)?; + } + } + Ok(js_obj) +} + // ClientGetUserDeviceError #[allow(dead_code)] @@ -8009,6 +8171,74 @@ fn claimer_user_initial_do_wait_peer(mut cx: FunctionContext) -> JsResult JsResult { + crate::init_sentry(); + let client = { + let js_val = cx.argument::(0)?; + { + let v = js_val.value(&mut cx); + if v < (u32::MIN as f64) || (u32::MAX as f64) < v { + cx.throw_type_error("Not an u32 number")? + } + let v = v as u32; + v + } + }; + let tos_updated_on = { + let js_val = cx.argument::(1)?; + { + let v = js_val.value(&mut cx); + let custom_from_rs_f64 = |n: f64| -> Result<_, &'static str> { + libparsec::DateTime::from_timestamp_micros((n * 1_000_000f64) as i64) + .map_err(|_| "Out-of-bound datetime") + }; + match custom_from_rs_f64(v) { + Ok(val) => val, + Err(err) => return cx.throw_type_error(err), + } + } + }; + let channel = cx.channel(); + let (deferred, promise) = cx.promise(); + + // TODO: Promises are not cancellable in Javascript by default, should we add a custom cancel method ? + let _handle = crate::TOKIO_RUNTIME + .lock() + .expect("Mutex is poisoned") + .spawn(async move { + let ret = libparsec::client_accept_tos(client, tos_updated_on).await; + + deferred.settle_with(&channel, move |mut cx| { + let js_ret = match ret { + Ok(ok) => { + let js_obj = JsObject::new(&mut cx); + let js_tag = JsBoolean::new(&mut cx, true); + js_obj.set(&mut cx, "ok", js_tag)?; + let js_value = { + #[allow(clippy::let_unit_value)] + let _ = ok; + JsNull::new(&mut cx) + }; + js_obj.set(&mut cx, "value", js_value)?; + js_obj + } + Err(err) => { + let js_obj = cx.empty_object(); + let js_tag = JsBoolean::new(&mut cx, false); + js_obj.set(&mut cx, "ok", js_tag)?; + let js_err = variant_client_accept_tos_error_rs_to_js(&mut cx, err)?; + js_obj.set(&mut cx, "error", js_err)?; + js_obj + } + }; + Ok(js_ret) + }); + }); + + Ok(promise) +} + // client_cancel_invitation fn client_cancel_invitation(mut cx: FunctionContext) -> JsResult { crate::init_sentry(); @@ -8205,6 +8435,56 @@ fn client_create_workspace(mut cx: FunctionContext) -> JsResult { Ok(promise) } +// client_get_tos +fn client_get_tos(mut cx: FunctionContext) -> JsResult { + crate::init_sentry(); + let client = { + let js_val = cx.argument::(0)?; + { + let v = js_val.value(&mut cx); + if v < (u32::MIN as f64) || (u32::MAX as f64) < v { + cx.throw_type_error("Not an u32 number")? + } + let v = v as u32; + v + } + }; + let channel = cx.channel(); + let (deferred, promise) = cx.promise(); + + // TODO: Promises are not cancellable in Javascript by default, should we add a custom cancel method ? + let _handle = crate::TOKIO_RUNTIME + .lock() + .expect("Mutex is poisoned") + .spawn(async move { + let ret = libparsec::client_get_tos(client).await; + + deferred.settle_with(&channel, move |mut cx| { + let js_ret = match ret { + Ok(ok) => { + let js_obj = JsObject::new(&mut cx); + let js_tag = JsBoolean::new(&mut cx, true); + js_obj.set(&mut cx, "ok", js_tag)?; + let js_value = struct_tos_rs_to_js(&mut cx, ok)?; + js_obj.set(&mut cx, "value", js_value)?; + js_obj + } + Err(err) => { + let js_obj = cx.empty_object(); + let js_tag = JsBoolean::new(&mut cx, false); + js_obj.set(&mut cx, "ok", js_tag)?; + let js_err = variant_client_get_tos_error_rs_to_js(&mut cx, err)?; + js_obj.set(&mut cx, "error", js_err)?; + js_obj + } + }; + Ok(js_ret) + }); + }); + + Ok(promise) +} + // client_get_user_device fn client_get_user_device(mut cx: FunctionContext) -> JsResult { crate::init_sentry(); @@ -12888,9 +13168,11 @@ pub fn register_meths(cx: &mut ModuleContext) -> NeonResult<()> { "claimerUserInitialDoWaitPeer", claimer_user_initial_do_wait_peer, )?; + cx.export_function("clientAcceptTos", client_accept_tos)?; cx.export_function("clientCancelInvitation", client_cancel_invitation)?; cx.export_function("clientChangeAuthentication", client_change_authentication)?; cx.export_function("clientCreateWorkspace", client_create_workspace)?; + cx.export_function("clientGetTos", client_get_tos)?; cx.export_function("clientGetUserDevice", client_get_user_device)?; cx.export_function("clientInfo", client_info)?; cx.export_function("clientListInvitations", client_list_invitations)?; diff --git a/bindings/web/src/meths.rs b/bindings/web/src/meths.rs index a6adcc6dd2d..a9893716d18 100644 --- a/bindings/web/src/meths.rs +++ b/bindings/web/src/meths.rs @@ -1771,6 +1771,91 @@ fn struct_started_workspace_info_rs_to_js( Ok(js_obj) } +// Tos + +#[allow(dead_code)] +fn struct_tos_js_to_rs(obj: JsValue) -> Result { + let per_locale_urls = { + let js_val = Reflect::get(&obj, &"perLocaleUrls".into())?; + { + let js_val = js_val + .dyn_into::() + .map_err(|_| TypeError::new("Not a Map"))?; + let mut converted = std::collections::HashMap::with_capacity(js_val.size() as usize); + let js_keys = js_val.keys(); + let js_values = js_val.values(); + loop { + let next_js_key = js_keys.next()?; + let next_js_value = js_values.next()?; + if next_js_key.done() { + assert!(next_js_value.done()); + break; + } + assert!(!next_js_value.done()); + + let js_key = next_js_key.value(); + let js_value = next_js_value.value(); + + let key = js_key + .dyn_into::() + .ok() + .and_then(|s| s.as_string()) + .ok_or_else(|| TypeError::new("Not a string"))?; + let value = js_value + .dyn_into::() + .ok() + .and_then(|s| s.as_string()) + .ok_or_else(|| TypeError::new("Not a string"))?; + converted.insert(key, value); + } + converted + } + }; + let updated_on = { + let js_val = Reflect::get(&obj, &"updatedOn".into())?; + { + let v = js_val.dyn_into::()?.value_of(); + let custom_from_rs_f64 = |n: f64| -> Result<_, &'static str> { + libparsec::DateTime::from_timestamp_micros((n * 1_000_000f64) as i64) + .map_err(|_| "Out-of-bound datetime") + }; + let v = custom_from_rs_f64(v).map_err(|e| TypeError::new(e.as_ref()))?; + v + } + }; + Ok(libparsec::Tos { + per_locale_urls, + updated_on, + }) +} + +#[allow(dead_code)] +fn struct_tos_rs_to_js(rs_obj: libparsec::Tos) -> Result { + let js_obj = Object::new().into(); + let js_per_locale_urls = { + let js_map = Map::new(); + for (key, value) in rs_obj.per_locale_urls.into_iter() { + let js_key = key.into(); + let js_value = value.into(); + js_map.set(&js_key, &js_value); + } + js_map.into() + }; + Reflect::set(&js_obj, &"perLocaleUrls".into(), &js_per_locale_urls)?; + let js_updated_on = { + let custom_to_rs_f64 = |dt: libparsec::DateTime| -> Result { + Ok((dt.as_timestamp_micros() as f64) / 1_000_000f64) + }; + let v = match custom_to_rs_f64(rs_obj.updated_on) { + Ok(ok) => ok, + Err(err) => return Err(JsValue::from(TypeError::new(err.as_ref()))), + }; + JsValue::from(v) + }; + Reflect::set(&js_obj, &"updatedOn".into(), &js_updated_on)?; + Ok(js_obj) +} + // UserClaimFinalizeInfo #[allow(dead_code)] @@ -2977,6 +3062,44 @@ fn variant_claimer_retrieve_info_error_rs_to_js( Ok(js_obj) } +// ClientAcceptTosError + +#[allow(dead_code)] +fn variant_client_accept_tos_error_rs_to_js( + rs_obj: libparsec::ClientAcceptTosError, +) -> Result { + let js_obj = Object::new().into(); + let js_display = &rs_obj.to_string(); + Reflect::set(&js_obj, &"error".into(), &js_display.into())?; + match rs_obj { + libparsec::ClientAcceptTosError::Internal { .. } => { + Reflect::set( + &js_obj, + &"tag".into(), + &"ClientAcceptTosErrorInternal".into(), + )?; + } + libparsec::ClientAcceptTosError::NoTos { .. } => { + Reflect::set(&js_obj, &"tag".into(), &"ClientAcceptTosErrorNoTos".into())?; + } + libparsec::ClientAcceptTosError::Offline { .. } => { + Reflect::set( + &js_obj, + &"tag".into(), + &"ClientAcceptTosErrorOffline".into(), + )?; + } + libparsec::ClientAcceptTosError::TosMismatch { .. } => { + Reflect::set( + &js_obj, + &"tag".into(), + &"ClientAcceptTosErrorTosMismatch".into(), + )?; + } + } + Ok(js_obj) +} + // ClientCancelInvitationError #[allow(dead_code)] @@ -3141,6 +3264,7 @@ fn variant_client_event_js_to_rs(obj: JsValue) -> Result Ok(libparsec::ClientEvent::MustAcceptTos {}), "ClientEventOffline" => Ok(libparsec::ClientEvent::Offline {}), "ClientEventOnline" => Ok(libparsec::ClientEvent::Online {}), "ClientEventPing" => { @@ -3488,6 +3612,9 @@ fn variant_client_event_rs_to_js(rs_obj: libparsec::ClientEvent) -> Result { + Reflect::set(&js_obj, &"tag".into(), &"ClientEventMustAcceptTos".into())?; + } libparsec::ClientEvent::Offline { .. } => { Reflect::set(&js_obj, &"tag".into(), &"ClientEventOffline".into())?; } @@ -3759,6 +3886,29 @@ fn variant_client_event_rs_to_js(rs_obj: libparsec::ClientEvent) -> Result Result { + let js_obj = Object::new().into(); + let js_display = &rs_obj.to_string(); + Reflect::set(&js_obj, &"error".into(), &js_display.into())?; + match rs_obj { + libparsec::ClientGetTosError::Internal { .. } => { + Reflect::set(&js_obj, &"tag".into(), &"ClientGetTosErrorInternal".into())?; + } + libparsec::ClientGetTosError::NoTos { .. } => { + Reflect::set(&js_obj, &"tag".into(), &"ClientGetTosErrorNoTos".into())?; + } + libparsec::ClientGetTosError::Offline { .. } => { + Reflect::set(&js_obj, &"tag".into(), &"ClientGetTosErrorOffline".into())?; + } + } + Ok(js_obj) +} + // ClientGetUserDeviceError #[allow(dead_code)] @@ -8352,6 +8502,42 @@ pub fn claimerUserInitialDoWaitPeer(canceller: u32, handle: u32) -> Promise { }) } +// client_accept_tos +#[allow(non_snake_case)] +#[wasm_bindgen] +pub fn clientAcceptTos(client: u32, tos_updated_on: f64) -> Promise { + future_to_promise(async move { + let tos_updated_on = { + let custom_from_rs_f64 = |n: f64| -> Result<_, &'static str> { + libparsec::DateTime::from_timestamp_micros((n * 1_000_000f64) as i64) + .map_err(|_| "Out-of-bound datetime") + }; + custom_from_rs_f64(tos_updated_on).map_err(|e| TypeError::new(e.as_ref())) + }?; + + let ret = libparsec::client_accept_tos(client, tos_updated_on).await; + Ok(match ret { + Ok(value) => { + let js_obj = Object::new().into(); + Reflect::set(&js_obj, &"ok".into(), &true.into())?; + let js_value = { + let _ = value; + JsValue::null() + }; + Reflect::set(&js_obj, &"value".into(), &js_value)?; + js_obj + } + Err(err) => { + let js_obj = Object::new().into(); + Reflect::set(&js_obj, &"ok".into(), &false.into())?; + let js_err = variant_client_accept_tos_error_rs_to_js(err)?; + Reflect::set(&js_obj, &"error".into(), &js_err)?; + js_obj + } + }) + }) +} + // client_cancel_invitation #[allow(non_snake_case)] #[wasm_bindgen] @@ -8467,6 +8653,31 @@ pub fn clientCreateWorkspace(client: u32, name: String) -> Promise { }) } +// client_get_tos +#[allow(non_snake_case)] +#[wasm_bindgen] +pub fn clientGetTos(client: u32) -> Promise { + future_to_promise(async move { + let ret = libparsec::client_get_tos(client).await; + Ok(match ret { + Ok(value) => { + let js_obj = Object::new().into(); + Reflect::set(&js_obj, &"ok".into(), &true.into())?; + let js_value = struct_tos_rs_to_js(value)?; + Reflect::set(&js_obj, &"value".into(), &js_value)?; + js_obj + } + Err(err) => { + let js_obj = Object::new().into(); + Reflect::set(&js_obj, &"ok".into(), &false.into())?; + let js_err = variant_client_get_tos_error_rs_to_js(err)?; + Reflect::set(&js_obj, &"error".into(), &js_err)?; + js_obj + } + }) + }) +} + // client_get_user_device #[allow(non_snake_case)] #[wasm_bindgen] diff --git a/client/src/plugins/libparsec/definitions.ts b/client/src/plugins/libparsec/definitions.ts index dc24964cf52..b3a867cf459 100644 --- a/client/src/plugins/libparsec/definitions.ts +++ b/client/src/plugins/libparsec/definitions.ts @@ -208,6 +208,11 @@ export interface StartedWorkspaceInfo { mountpoints: Array<[Handle, Path]> } +export interface Tos { + perLocaleUrls: Map + updatedOn: DateTime +} + export interface UserClaimFinalizeInfo { handle: Handle } @@ -493,6 +498,36 @@ export type ClaimerRetrieveInfoError = | ClaimerRetrieveInfoErrorNotFound | ClaimerRetrieveInfoErrorOffline +// ClientAcceptTosError +export enum ClientAcceptTosErrorTag { + Internal = 'ClientAcceptTosErrorInternal', + NoTos = 'ClientAcceptTosErrorNoTos', + Offline = 'ClientAcceptTosErrorOffline', + TosMismatch = 'ClientAcceptTosErrorTosMismatch', +} + +export interface ClientAcceptTosErrorInternal { + tag: ClientAcceptTosErrorTag.Internal + error: string +} +export interface ClientAcceptTosErrorNoTos { + tag: ClientAcceptTosErrorTag.NoTos + error: string +} +export interface ClientAcceptTosErrorOffline { + tag: ClientAcceptTosErrorTag.Offline + error: string +} +export interface ClientAcceptTosErrorTosMismatch { + tag: ClientAcceptTosErrorTag.TosMismatch + error: string +} +export type ClientAcceptTosError = + | ClientAcceptTosErrorInternal + | ClientAcceptTosErrorNoTos + | ClientAcceptTosErrorOffline + | ClientAcceptTosErrorTosMismatch + // ClientCancelInvitationError export enum ClientCancelInvitationErrorTag { AlreadyDeleted = 'ClientCancelInvitationErrorAlreadyDeleted', @@ -576,6 +611,7 @@ export enum ClientEventTag { ExpiredOrganization = 'ClientEventExpiredOrganization', IncompatibleServer = 'ClientEventIncompatibleServer', InvitationChanged = 'ClientEventInvitationChanged', + MustAcceptTos = 'ClientEventMustAcceptTos', Offline = 'ClientEventOffline', Online = 'ClientEventOnline', Ping = 'ClientEventPing', @@ -604,6 +640,9 @@ export interface ClientEventInvitationChanged { token: InvitationToken status: InvitationStatus } +export interface ClientEventMustAcceptTos { + tag: ClientEventTag.MustAcceptTos +} export interface ClientEventOffline { tag: ClientEventTag.Offline } @@ -670,6 +709,7 @@ export type ClientEvent = | ClientEventExpiredOrganization | ClientEventIncompatibleServer | ClientEventInvitationChanged + | ClientEventMustAcceptTos | ClientEventOffline | ClientEventOnline | ClientEventPing @@ -685,6 +725,30 @@ export type ClientEvent = | ClientEventWorkspaceWatchedEntryChanged | ClientEventWorkspacesSelfListChanged +// ClientGetTosError +export enum ClientGetTosErrorTag { + Internal = 'ClientGetTosErrorInternal', + NoTos = 'ClientGetTosErrorNoTos', + Offline = 'ClientGetTosErrorOffline', +} + +export interface ClientGetTosErrorInternal { + tag: ClientGetTosErrorTag.Internal + error: string +} +export interface ClientGetTosErrorNoTos { + tag: ClientGetTosErrorTag.NoTos + error: string +} +export interface ClientGetTosErrorOffline { + tag: ClientGetTosErrorTag.Offline + error: string +} +export type ClientGetTosError = + | ClientGetTosErrorInternal + | ClientGetTosErrorNoTos + | ClientGetTosErrorOffline + // ClientGetUserDeviceError export enum ClientGetUserDeviceErrorTag { Internal = 'ClientGetUserDeviceErrorInternal', @@ -2523,6 +2587,10 @@ export interface LibParsecPlugin { canceller: Handle, handle: Handle ): Promise> + clientAcceptTos( + client: Handle, + tos_updated_on: DateTime + ): Promise> clientCancelInvitation( client: Handle, token: InvitationToken @@ -2536,6 +2604,9 @@ export interface LibParsecPlugin { client: Handle, name: EntryName ): Promise> + clientGetTos( + client: Handle + ): Promise> clientGetUserDevice( client: Handle, device: DeviceID