Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
609c4cee8c | ||
|
|
c7e51c2e48 | ||
|
|
703f44d731 | ||
|
|
7be3934c86 | ||
|
|
f224347836 |
@@ -46,7 +46,8 @@ import AVFoundation
|
||||
//
|
||||
// VoIP configuration is engaged on voice-channel join via the
|
||||
// `chanora/ios_audio_session` MethodChannel, driven from Dart
|
||||
// by the BridgeEvent::AudioStarted / AudioStopped lifecycle.
|
||||
// before `voiceJoin` starts VoiceProcessingIO and again as an
|
||||
// idempotent guard on the AudioStarted lifecycle.
|
||||
do {
|
||||
try AVAudioSession.sharedInstance().setCategory(.ambient, mode: .default)
|
||||
logAudioSessionState(context: "launch-ambient")
|
||||
@@ -79,8 +80,8 @@ import AVFoundation
|
||||
}
|
||||
|
||||
/// Activate the VoIP audio session. Called from Dart via the
|
||||
/// `chanora/ios_audio_session` channel when a voice channel join
|
||||
/// reaches the `BridgeEvent::AudioStarted` stage. Configures
|
||||
/// `chanora/ios_audio_session` channel before a voice channel join
|
||||
/// starts VoiceProcessingIO. Configures
|
||||
/// .playAndRecord + .voiceChat with .mixWithOthers so other apps
|
||||
/// (Spotify, podcasts) can keep playing alongside the voice
|
||||
/// channel — matching the Telegram group-call UX. Idempotent:
|
||||
|
||||
@@ -34,6 +34,7 @@ import 'services/prefetch_debouncer.dart';
|
||||
import 'services/snapshot_state_mapper.dart';
|
||||
import 'services/ts3_server_link.dart';
|
||||
import 'services/ui_preferences_service.dart';
|
||||
import 'services/voice_join_ordering.dart';
|
||||
import 'src/rust/api.dart' as rust;
|
||||
import 'src/rust/frb_generated.dart';
|
||||
import 'src/rust/lib.dart' as rust_err;
|
||||
@@ -1301,7 +1302,18 @@ class _BetaHomeState extends State<_BetaHome> with WidgetsBindingObserver {
|
||||
});
|
||||
}
|
||||
}
|
||||
await rust.voiceJoin(channelId: ch.id, password: password ?? '');
|
||||
await joinVoiceChannelWithIosAudioSession(
|
||||
channelId: ch.id,
|
||||
password: password ?? '',
|
||||
voiceJoin: rust.voiceJoin,
|
||||
activateIosAudioSession: iosAudioSessionController.activate,
|
||||
deactivateIosAudioSession: iosAudioSessionController.deactivate,
|
||||
// Server says we are already in the target channel: the user is
|
||||
// still joined to a voice channel, so the iOS audio session must
|
||||
// stay active. The catch below converts this rethrow into the
|
||||
// success-on-already-joined branch.
|
||||
isJoinSuccess: _isAlreadyInChannel,
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_currentVoiceChannelId = ch.id;
|
||||
|
||||
@@ -10,9 +10,9 @@ const iosAudioSessionChannelName = 'chanora/ios_audio_session';
|
||||
/// launch and leaves it inactive. The session is only switched to
|
||||
/// `.playAndRecord` + `.voiceChat` (with `.mixWithOthers`) while a
|
||||
/// voice channel is actually active. This controller is the Dart
|
||||
/// side of that contract — call [activate] when the Rust engine
|
||||
/// emits `BridgeEvent::AudioStarted` and [deactivate] on
|
||||
/// `BridgeEvent::AudioStopped`.
|
||||
/// side of that contract — call [activate] before the Rust engine
|
||||
/// starts VoiceProcessingIO and [deactivate] on
|
||||
/// `BridgeEvent::AudioStopped` or failed joins.
|
||||
///
|
||||
/// On non-iOS platforms both methods are no-ops; the platforms
|
||||
/// handle their own session lifecycle elsewhere (Android via
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
typedef VoiceJoinCallback = Future<void> Function({
|
||||
required BigInt channelId,
|
||||
required String password,
|
||||
});
|
||||
|
||||
typedef IosVoiceSessionActivation = Future<void> Function();
|
||||
typedef IosVoiceSessionDeactivation = Future<void> Function();
|
||||
|
||||
/// Predicate used to recognise `voiceJoin` errors that the caller treats as a
|
||||
/// successful join outcome (e.g. the server replied "already in channel").
|
||||
///
|
||||
/// When this returns `true` for a thrown error, the iOS audio session is kept
|
||||
/// active because the user is still considered joined to the channel. The
|
||||
/// error is still rethrown so the caller can run its success-on-already-joined
|
||||
/// branch and update local state.
|
||||
typedef VoiceJoinSuccessPredicate = bool Function(Object error);
|
||||
|
||||
Future<void> joinVoiceChannelWithIosAudioSession({
|
||||
required BigInt channelId,
|
||||
required String password,
|
||||
required VoiceJoinCallback voiceJoin,
|
||||
required IosVoiceSessionActivation activateIosAudioSession,
|
||||
required IosVoiceSessionDeactivation deactivateIosAudioSession,
|
||||
VoiceJoinSuccessPredicate? isJoinSuccess,
|
||||
}) async {
|
||||
await activateIosAudioSession();
|
||||
try {
|
||||
await voiceJoin(channelId: channelId, password: password);
|
||||
} catch (e) {
|
||||
if (isJoinSuccess != null && isJoinSuccess(e)) {
|
||||
rethrow;
|
||||
}
|
||||
await deactivateIosAudioSession();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:chanora_flutter/services/voice_join_ordering.dart';
|
||||
|
||||
void main() {
|
||||
group('joinVoiceChannelWithIosAudioSession', () {
|
||||
test('activates the iOS audio session before Rust voiceJoin', () async {
|
||||
final calls = <String>[];
|
||||
|
||||
await joinVoiceChannelWithIosAudioSession(
|
||||
channelId: BigInt.from(42),
|
||||
password: 'secret',
|
||||
activateIosAudioSession: () async {
|
||||
calls.add('activateIosAudioSession');
|
||||
},
|
||||
deactivateIosAudioSession: () async {
|
||||
calls.add('deactivateIosAudioSession');
|
||||
},
|
||||
voiceJoin: ({required channelId, required password}) async {
|
||||
expect(channelId, BigInt.from(42));
|
||||
expect(password, 'secret');
|
||||
calls.add('voiceJoin');
|
||||
},
|
||||
);
|
||||
|
||||
expect(calls, ['activateIosAudioSession', 'voiceJoin']);
|
||||
});
|
||||
|
||||
test('deactivates the iOS audio session when Rust voiceJoin fails',
|
||||
() async {
|
||||
final calls = <String>[];
|
||||
|
||||
await expectLater(
|
||||
joinVoiceChannelWithIosAudioSession(
|
||||
channelId: BigInt.from(42),
|
||||
password: '',
|
||||
activateIosAudioSession: () async {
|
||||
calls.add('activateIosAudioSession');
|
||||
},
|
||||
deactivateIosAudioSession: () async {
|
||||
calls.add('deactivateIosAudioSession');
|
||||
},
|
||||
voiceJoin: ({required channelId, required password}) async {
|
||||
calls.add('voiceJoin');
|
||||
throw StateError('join rejected');
|
||||
},
|
||||
),
|
||||
throwsStateError,
|
||||
);
|
||||
|
||||
expect(calls, [
|
||||
'activateIosAudioSession',
|
||||
'voiceJoin',
|
||||
'deactivateIosAudioSession',
|
||||
]);
|
||||
});
|
||||
|
||||
test(
|
||||
'keeps the iOS audio session active when voiceJoin throws but the '
|
||||
'error is recognised as already-in-channel (treated as success); '
|
||||
'still rethrows so the caller runs its success-on-already-joined branch',
|
||||
() async {
|
||||
final calls = <String>[];
|
||||
|
||||
await expectLater(
|
||||
joinVoiceChannelWithIosAudioSession(
|
||||
channelId: BigInt.from(42),
|
||||
password: '',
|
||||
activateIosAudioSession: () async {
|
||||
calls.add('activateIosAudioSession');
|
||||
},
|
||||
deactivateIosAudioSession: () async {
|
||||
calls.add('deactivateIosAudioSession');
|
||||
},
|
||||
voiceJoin: ({required channelId, required password}) async {
|
||||
calls.add('voiceJoin');
|
||||
throw _FakeAlreadyInChannel();
|
||||
},
|
||||
isJoinSuccess: (error) => error is _FakeAlreadyInChannel,
|
||||
),
|
||||
throwsA(isA<_FakeAlreadyInChannel>()),
|
||||
);
|
||||
|
||||
expect(calls, ['activateIosAudioSession', 'voiceJoin']);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'deactivates the iOS audio session when isJoinSuccess returns false '
|
||||
'for a non-success error',
|
||||
() async {
|
||||
final calls = <String>[];
|
||||
|
||||
await expectLater(
|
||||
joinVoiceChannelWithIosAudioSession(
|
||||
channelId: BigInt.from(42),
|
||||
password: '',
|
||||
activateIosAudioSession: () async {
|
||||
calls.add('activateIosAudioSession');
|
||||
},
|
||||
deactivateIosAudioSession: () async {
|
||||
calls.add('deactivateIosAudioSession');
|
||||
},
|
||||
voiceJoin: ({required channelId, required password}) async {
|
||||
calls.add('voiceJoin');
|
||||
throw StateError('join rejected');
|
||||
},
|
||||
isJoinSuccess: (error) => error is _FakeAlreadyInChannel,
|
||||
),
|
||||
throwsStateError,
|
||||
);
|
||||
|
||||
expect(calls, [
|
||||
'activateIosAudioSession',
|
||||
'voiceJoin',
|
||||
'deactivateIosAudioSession',
|
||||
]);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
class _FakeAlreadyInChannel implements Exception {}
|
||||
@@ -49,6 +49,11 @@ terms.
|
||||
| `flutter` | 0.0.0 | sdk | yes |
|
||||
| `flutter_foreground_task` | 9.2.2 | hosted | yes |
|
||||
| `flutter_lints` | 6.0.0 | hosted | yes |
|
||||
| `flutter_local_notifications` | 22.0.0 | hosted | yes |
|
||||
| `flutter_local_notifications_linux` | 8.0.1 | hosted | yes |
|
||||
| `flutter_local_notifications_platform_interface` | 12.0.0 | hosted | yes |
|
||||
| `flutter_local_notifications_web` | 1.0.0 | hosted | yes |
|
||||
| `flutter_local_notifications_windows` | 3.1.0 | hosted | yes |
|
||||
| `flutter_localizations` | 0.0.0 | sdk | yes |
|
||||
| `flutter_rust_bridge` | 2.12.0 | hosted | yes |
|
||||
| `flutter_test` | 0.0.0 | sdk | yes |
|
||||
@@ -117,6 +122,7 @@ terms.
|
||||
| `string_scanner` | 1.4.1 | hosted | yes |
|
||||
| `term_glyph` | 1.2.2 | hosted | yes |
|
||||
| `test_api` | 0.7.11 | hosted | yes |
|
||||
| `timezone` | 0.11.0 | hosted | yes |
|
||||
| `typed_data` | 1.4.0 | hosted | yes |
|
||||
| `url_launcher` | 6.3.2 | hosted | yes |
|
||||
| `url_launcher_android` | 6.3.30 | hosted | yes |
|
||||
@@ -1869,6 +1875,166 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### flutter_local_notifications 22.0.0
|
||||
|
||||
```
|
||||
Copyright 2018 Michael Bui. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### flutter_local_notifications_linux 8.0.1
|
||||
|
||||
```
|
||||
Copyright 2018 Michael Bui. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### flutter_local_notifications_platform_interface 12.0.0
|
||||
|
||||
```
|
||||
Copyright 2020 Michael Bui. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### flutter_local_notifications_web 1.0.0
|
||||
|
||||
```
|
||||
Copyright 2020 Michael Bui. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### flutter_local_notifications_windows 3.1.0
|
||||
|
||||
```
|
||||
Copyright 2024 Michael Bui. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### flutter_localizations 0.0.0
|
||||
|
||||
```
|
||||
@@ -4673,6 +4839,33 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### timezone 0.11.0
|
||||
|
||||
```
|
||||
Copyright (c) 2014, timezone project authors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
### typed_data 1.4.0
|
||||
|
||||
```
|
||||
|
||||
@@ -291,7 +291,7 @@ those terms.
|
||||
| chanora_diagnostics | 0.2.0-beta.1 | `Apache License 2.0` | <https://github.com/anomalyco/opencode> |
|
||||
| chanora_prefetch | 0.2.0-beta.1 | `Apache License 2.0` | <https://github.com/anomalyco/opencode> |
|
||||
| chanora_protocol | 0.2.0-beta.1 | `Apache License 2.0` | <https://github.com/anomalyco/opencode> |
|
||||
| chanora_resolver | 0.1.0 | `Apache License 2.0` | — |
|
||||
| chanora_resolver | 0.2.0-beta.1 | `Apache License 2.0` | — |
|
||||
| chanora_state | 0.2.0-beta.1 | `Apache License 2.0` | <https://github.com/anomalyco/opencode> |
|
||||
| chanora_storage | 0.2.0-beta.1 | `Apache License 2.0` | <https://github.com/anomalyco/opencode> |
|
||||
| alsa | 0.11.0 | `Apache License 2.0` | <https://github.com/diwic/alsa-rs> |
|
||||
@@ -10967,3 +10967,4 @@ cargo about generate --output-file docs/security/license-inventory.html about.hb
|
||||
|
||||
This artefact supports the DEC-012 legal review handoff at
|
||||
`docs/governance/legal-review-readiness.md`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user